]>
Commit | Line | Data |
---|---|---|
718e3744 | 1 | /* |
2 | * Memory management routine | |
3 | * Copyright (C) 1998 Kunihiro Ishiguro | |
4 | * | |
5 | * This file is part of GNU Zebra. | |
6 | * | |
7 | * GNU Zebra 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 | |
9 | * Free Software Foundation; either version 2, or (at your option) any | |
10 | * later version. | |
11 | * | |
12 | * GNU Zebra is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with GNU Zebra; see the file COPYING. If not, write to the Free | |
19 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
20 | * 02111-1307, USA. | |
21 | */ | |
22 | ||
23 | #include <zebra.h> | |
d09552d0 | 24 | /* malloc.h is generally obsolete, however GNU Libc mallinfo wants it. */ |
74176d22 | 25 | #if !defined(HAVE_STDLIB_H) || (defined(GNU_LINUX) && defined(HAVE_MALLINFO)) |
41be32bf | 26 | #include <malloc.h> |
d09552d0 | 27 | #endif /* !HAVE_STDLIB_H || HAVE_MALLINFO */ |
718e3744 | 28 | |
29 | #include "log.h" | |
30 | #include "memory.h" | |
fc7948fa | 31 | #include "memory_vty.h" |
6b0655a2 | 32 | |
718e3744 | 33 | /* Looking up memory status from vty interface. */ |
34 | #include "vector.h" | |
35 | #include "vty.h" | |
36 | #include "command.h" | |
37 | ||
228da428 CC |
38 | void |
39 | log_memstats_stderr (const char *prefix) | |
40 | { | |
fc7948fa | 41 | #if 0 |
228da428 CC |
42 | struct mlist *ml; |
43 | struct memory_list *m; | |
44 | int i; | |
45 | int j = 0; | |
46 | ||
47 | for (ml = mlists; ml->list; ml++) | |
48 | { | |
49 | i = 0; | |
50 | ||
51 | for (m = ml->list; m->index >= 0; m++) | |
52 | if (m->index && mstat[m->index].alloc) | |
53 | { | |
54 | if (!i) | |
55 | fprintf (stderr, | |
56 | "%s: memstats: Current memory utilization in module %s:\n", | |
57 | prefix, | |
58 | ml->name); | |
59 | fprintf (stderr, | |
60 | "%s: memstats: %-30s: %10ld%s\n", | |
61 | prefix, | |
62 | m->format, | |
63 | mstat[m->index].alloc, | |
64 | mstat[m->index].alloc < 0 ? " (REPORT THIS BUG!)" : ""); | |
65 | i = j = 1; | |
66 | } | |
67 | } | |
68 | ||
69 | if (j) | |
70 | fprintf (stderr, | |
71 | "%s: memstats: NOTE: If configuration exists, utilization may be " | |
72 | "expected.\n", | |
73 | prefix); | |
74 | else | |
75 | fprintf (stderr, | |
76 | "%s: memstats: No remaining tracked memory utilization.\n", | |
77 | prefix); | |
fc7948fa | 78 | #endif |
228da428 CC |
79 | } |
80 | ||
fc7948fa | 81 | #if 0 |
24065a3d | 82 | static void |
83 | show_separator(struct vty *vty) | |
718e3744 | 84 | { |
24065a3d | 85 | vty_out (vty, "-----------------------------\r\n"); |
86 | } | |
718e3744 | 87 | |
24065a3d | 88 | static int |
718e3744 | 89 | show_memory_vty (struct vty *vty, struct memory_list *list) |
90 | { | |
91 | struct memory_list *m; | |
24065a3d | 92 | int needsep = 0; |
718e3744 | 93 | |
94 | for (m = list; m->index >= 0; m++) | |
95 | if (m->index == 0) | |
24065a3d | 96 | { |
97 | if (needsep) | |
98 | { | |
99 | show_separator (vty); | |
100 | needsep = 0; | |
101 | } | |
102 | } | |
103 | else if (mstat[m->index].alloc) | |
104 | { | |
105 | vty_out (vty, "%-30s: %10ld\r\n", m->format, mstat[m->index].alloc); | |
106 | needsep = 1; | |
107 | } | |
108 | return needsep; | |
718e3744 | 109 | } |
fc7948fa | 110 | #endif |
718e3744 | 111 | |
41be32bf PJ |
112 | #ifdef HAVE_MALLINFO |
113 | static int | |
114 | show_memory_mallinfo (struct vty *vty) | |
115 | { | |
116 | struct mallinfo minfo = mallinfo(); | |
117 | char buf[MTYPE_MEMSTR_LEN]; | |
118 | ||
119 | vty_out (vty, "System allocator statistics:%s", VTY_NEWLINE); | |
120 | vty_out (vty, " Total heap allocated: %s%s", | |
121 | mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.arena), | |
122 | VTY_NEWLINE); | |
123 | vty_out (vty, " Holding block headers: %s%s", | |
124 | mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.hblkhd), | |
125 | VTY_NEWLINE); | |
126 | vty_out (vty, " Used small blocks: %s%s", | |
127 | mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.usmblks), | |
128 | VTY_NEWLINE); | |
129 | vty_out (vty, " Used ordinary blocks: %s%s", | |
130 | mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.uordblks), | |
131 | VTY_NEWLINE); | |
132 | vty_out (vty, " Free small blocks: %s%s", | |
133 | mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.fsmblks), | |
134 | VTY_NEWLINE); | |
135 | vty_out (vty, " Free ordinary blocks: %s%s", | |
136 | mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.fordblks), | |
137 | VTY_NEWLINE); | |
138 | vty_out (vty, " Ordinary blocks: %ld%s", | |
139 | (unsigned long)minfo.ordblks, | |
140 | VTY_NEWLINE); | |
141 | vty_out (vty, " Small blocks: %ld%s", | |
142 | (unsigned long)minfo.smblks, | |
143 | VTY_NEWLINE); | |
144 | vty_out (vty, " Holding blocks: %ld%s", | |
145 | (unsigned long)minfo.hblks, | |
146 | VTY_NEWLINE); | |
147 | vty_out (vty, "(see system documentation for 'mallinfo' for meaning)%s", | |
148 | VTY_NEWLINE); | |
149 | return 1; | |
150 | } | |
151 | #endif /* HAVE_MALLINFO */ | |
152 | ||
3b4cd783 DL |
153 | static int qmem_walker(void *arg, struct memgroup *mg, struct memtype *mt) |
154 | { | |
155 | struct vty *vty = arg; | |
156 | if (!mt) | |
157 | vty_out (vty, "--- qmem %s ---%s", mg->name, VTY_NEWLINE); | |
158 | else { | |
159 | char size[32]; | |
160 | snprintf(size, sizeof(size), "%6zu", mt->size); | |
161 | vty_out (vty, "%-30s: %10zu %s%s", | |
162 | mt->name, mt->n_alloc, | |
163 | mt->size == 0 ? "" : | |
164 | mt->size == SIZE_VAR ? "(variably sized)" : | |
165 | size, VTY_NEWLINE); | |
166 | } | |
167 | return 0; | |
168 | } | |
169 | ||
170 | ||
0d05fa51 DS |
171 | DEFUN (show_memory, |
172 | show_memory_cmd, | |
173 | "show memory", | |
718e3744 | 174 | "Show running system information\n" |
0d05fa51 | 175 | "Memory statistics\n") |
718e3744 | 176 | { |
24065a3d | 177 | int needsep = 0; |
41be32bf PJ |
178 | |
179 | #ifdef HAVE_MALLINFO | |
180 | needsep = show_memory_mallinfo (vty); | |
181 | #endif /* HAVE_MALLINFO */ | |
fc7948fa DL |
182 | |
183 | (void) needsep; | |
184 | #if 0 | |
185 | struct mlist *ml; | |
7fa25ff6 | 186 | for (ml = mlists; ml->list; ml++) |
187 | { | |
24065a3d | 188 | if (needsep) |
189 | show_separator (vty); | |
190 | needsep = show_memory_vty (vty, ml->list); | |
7fa25ff6 | 191 | } |
fc7948fa | 192 | #endif |
718e3744 | 193 | |
3b4cd783 | 194 | qmem_walk(qmem_walker, vty); |
718e3744 | 195 | return CMD_SUCCESS; |
196 | } | |
197 | ||
718e3744 | 198 | void |
f858e49b | 199 | memory_init (void) |
718e3744 | 200 | { |
62687ff1 | 201 | install_element (RESTRICTED_NODE, &show_memory_cmd); |
62687ff1 | 202 | |
718e3744 | 203 | install_element (VIEW_NODE, &show_memory_cmd); |
718e3744 | 204 | |
205 | install_element (ENABLE_NODE, &show_memory_cmd); | |
718e3744 | 206 | } |
6b0655a2 | 207 | |
41be32bf PJ |
208 | /* Stats querying from users */ |
209 | /* Return a pointer to a human friendly string describing | |
210 | * the byte count passed in. E.g: | |
211 | * "0 bytes", "2048 bytes", "110kB", "500MiB", "11GiB", etc. | |
212 | * Up to 4 significant figures will be given. | |
213 | * The pointer returned may be NULL (indicating an error) | |
214 | * or point to the given buffer, or point to static storage. | |
215 | */ | |
216 | const char * | |
217 | mtype_memstr (char *buf, size_t len, unsigned long bytes) | |
218 | { | |
6896f650 DS |
219 | unsigned int m, k; |
220 | ||
41be32bf PJ |
221 | /* easy cases */ |
222 | if (!bytes) | |
223 | return "0 bytes"; | |
224 | if (bytes == 1) | |
225 | return "1 byte"; | |
6896f650 DS |
226 | |
227 | /* | |
228 | * When we pass the 2gb barrier mallinfo() can no longer report | |
229 | * correct data so it just does something odd... | |
230 | * Reporting like Terrabytes of data. Which makes users... | |
231 | * edgy.. yes edgy that's the term for it. | |
232 | * So let's just give up gracefully | |
233 | */ | |
234 | if (bytes > 0x7fffffff) | |
235 | return "> 2GB"; | |
236 | ||
41be32bf PJ |
237 | m = bytes >> 20; |
238 | k = bytes >> 10; | |
6896f650 DS |
239 | |
240 | if (m > 10) | |
41be32bf PJ |
241 | { |
242 | if (bytes & (1 << 19)) | |
243 | m++; | |
244 | snprintf (buf, len, "%d MiB", m); | |
245 | } | |
246 | else if (k > 10) | |
247 | { | |
248 | if (bytes & (1 << 9)) | |
249 | k++; | |
250 | snprintf (buf, len, "%d KiB", k); | |
251 | } | |
252 | else | |
253 | snprintf (buf, len, "%ld bytes", bytes); | |
254 | ||
255 | return buf; | |
256 | } |