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