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