]> git.proxmox.com Git - mirror_frr.git/blob - lib/memory_vty.c
Merge pull request #2934 from LabNConsulting/working/master/rfapi_topotest_support
[mirror_frr.git] / lib / memory_vty.c
1 /*
2 * Memory and dynamic module VTY routine
3 *
4 * Copyright (C) 1998 Kunihiro Ishiguro
5 * Copyright (C) 2016-2017 David Lamparter for NetDEF, Inc.
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #include <zebra.h>
23 /* malloc.h is generally obsolete, however GNU Libc mallinfo wants it. */
24 #ifdef HAVE_MALLOC_H
25 #include <malloc.h>
26 #endif
27 #ifdef HAVE_MALLOC_MALLOC_H
28 #include <malloc/malloc.h>
29 #endif
30 #include <dlfcn.h>
31 #include <link.h>
32
33 #include "log.h"
34 #include "memory.h"
35 #include "module.h"
36 #include "memory_vty.h"
37
38 /* Looking up memory status from vty interface. */
39 #include "vector.h"
40 #include "vty.h"
41 #include "command.h"
42
43 #ifdef HAVE_MALLINFO
44 static int show_memory_mallinfo(struct vty *vty)
45 {
46 struct mallinfo minfo = mallinfo();
47 char buf[MTYPE_MEMSTR_LEN];
48
49 vty_out(vty, "System allocator statistics:\n");
50 vty_out(vty, " Total heap allocated: %s\n",
51 mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.arena));
52 vty_out(vty, " Holding block headers: %s\n",
53 mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.hblkhd));
54 vty_out(vty, " Used small blocks: %s\n",
55 mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.usmblks));
56 vty_out(vty, " Used ordinary blocks: %s\n",
57 mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.uordblks));
58 vty_out(vty, " Free small blocks: %s\n",
59 mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.fsmblks));
60 vty_out(vty, " Free ordinary blocks: %s\n",
61 mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.fordblks));
62 vty_out(vty, " Ordinary blocks: %ld\n",
63 (unsigned long)minfo.ordblks);
64 vty_out(vty, " Small blocks: %ld\n",
65 (unsigned long)minfo.smblks);
66 vty_out(vty, " Holding blocks: %ld\n",
67 (unsigned long)minfo.hblks);
68 vty_out(vty, "(see system documentation for 'mallinfo' for meaning)\n");
69 return 1;
70 }
71 #endif /* HAVE_MALLINFO */
72
73 static int qmem_walker(void *arg, struct memgroup *mg, struct memtype *mt)
74 {
75 struct vty *vty = arg;
76 if (!mt) {
77 vty_out(vty, "--- qmem %s ---\n", mg->name);
78 vty_out(vty, "%-30s: %8s %-8s%s %8s %9s\n",
79 "Type", "Current#", " Size",
80 #ifdef HAVE_MALLOC_USABLE_SIZE
81 " Total",
82 #else
83 "",
84 #endif
85 "Max#",
86 #ifdef HAVE_MALLOC_USABLE_SIZE
87 "MaxBytes"
88 #else
89 ""
90 #endif
91 );
92 } else {
93 if (mt->n_alloc != 0) {
94 char size[32];
95 snprintf(size, sizeof(size), "%6zu", mt->size);
96 #ifdef HAVE_MALLOC_USABLE_SIZE
97 #define TSTR " %9zu"
98 #define TARG , mt->total
99 #define TARG2 , mt->max_size
100 #else
101 #define TSTR ""
102 #define TARG
103 #define TARG2
104 #endif
105 vty_out(vty, "%-30s: %8zu %-8s"TSTR" %8zu"TSTR"\n",
106 mt->name,
107 mt->n_alloc,
108 mt->size == 0 ? ""
109 : mt->size == SIZE_VAR
110 ? "variable"
111 : size
112 TARG,
113 mt->n_max
114 TARG2);
115 }
116 }
117 return 0;
118 }
119
120
121 DEFUN (show_memory,
122 show_memory_cmd,
123 "show memory",
124 "Show running system information\n"
125 "Memory statistics\n")
126 {
127 #ifdef HAVE_MALLINFO
128 show_memory_mallinfo(vty);
129 #endif /* HAVE_MALLINFO */
130
131 qmem_walk(qmem_walker, vty);
132 return CMD_SUCCESS;
133 }
134
135 DEFUN (show_modules,
136 show_modules_cmd,
137 "show modules",
138 "Show running system information\n"
139 "Loaded modules\n")
140 {
141 struct frrmod_runtime *plug = frrmod_list;
142
143 vty_out(vty, "%-12s %-25s %s\n\n", "Module Name", "Version",
144 "Description");
145 while (plug) {
146 const struct frrmod_info *i = plug->info;
147
148 vty_out(vty, "%-12s %-25s %s\n", i->name, i->version,
149 i->description);
150 if (plug->dl_handle) {
151 #ifdef HAVE_DLINFO_ORIGIN
152 char origin[MAXPATHLEN] = "";
153 dlinfo(plug->dl_handle, RTLD_DI_ORIGIN, &origin);
154 #ifdef HAVE_DLINFO_LINKMAP
155 const char *name;
156 struct link_map *lm = NULL;
157 dlinfo(plug->dl_handle, RTLD_DI_LINKMAP, &lm);
158 if (lm) {
159 name = strrchr(lm->l_name, '/');
160 name = name ? name + 1 : lm->l_name;
161 vty_out(vty, "\tfrom: %s/%s\n", origin, name);
162 }
163 #else
164 vty_out(vty, "\tfrom: %s \n", origin, plug->load_name);
165 #endif
166 #else
167 vty_out(vty, "\tfrom: %s\n", plug->load_name);
168 #endif
169 }
170 plug = plug->next;
171 }
172 return CMD_SUCCESS;
173 }
174
175 void memory_init(void)
176 {
177 install_element(VIEW_NODE, &show_memory_cmd);
178 install_element(VIEW_NODE, &show_modules_cmd);
179 }
180
181 /* Stats querying from users */
182 /* Return a pointer to a human friendly string describing
183 * the byte count passed in. E.g:
184 * "0 bytes", "2048 bytes", "110kB", "500MiB", "11GiB", etc.
185 * Up to 4 significant figures will be given.
186 * The pointer returned may be NULL (indicating an error)
187 * or point to the given buffer, or point to static storage.
188 */
189 const char *mtype_memstr(char *buf, size_t len, unsigned long bytes)
190 {
191 unsigned int m, k;
192
193 /* easy cases */
194 if (!bytes)
195 return "0 bytes";
196 if (bytes == 1)
197 return "1 byte";
198
199 /*
200 * When we pass the 2gb barrier mallinfo() can no longer report
201 * correct data so it just does something odd...
202 * Reporting like Terrabytes of data. Which makes users...
203 * edgy.. yes edgy that's the term for it.
204 * So let's just give up gracefully
205 */
206 if (bytes > 0x7fffffff)
207 return "> 2GB";
208
209 m = bytes >> 20;
210 k = bytes >> 10;
211
212 if (m > 10) {
213 if (bytes & (1 << 19))
214 m++;
215 snprintf(buf, len, "%d MiB", m);
216 } else if (k > 10) {
217 if (bytes & (1 << 9))
218 k++;
219 snprintf(buf, len, "%d KiB", k);
220 } else
221 snprintf(buf, len, "%ld bytes", bytes);
222
223 return buf;
224 }