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