blob: 99ea0c1a71383218fd94c2799e9ba3b71773f56a [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15/*
16 Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus
17
18 Permission is hereby granted, free of charge, to any person obtaining
19 a copy of this software and associated documentation files (the
20 "Software"), to deal in the Software without restriction, including
21 without limitation the rights to use, copy, modify, merge, publish,
22 distribute, sublicense, and/or sell copies of the Software, and to
23 permit persons to whom the Software is furnished to do so, subject to
24 the following conditions:
25
26 The above copyright notice and this permission notice shall be
27 included in all copies or substantial portions of the Software.
28
29 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36*/
37
38#include <vppinfra/format.h>
Damjan Mariona7e83ce2016-06-09 12:38:22 +020039#include <ctype.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070040
41/* Format vectors. */
Dave Barachc3799992016-08-15 11:12:27 -040042u8 *
43format_vec32 (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -070044{
Dave Barachc3799992016-08-15 11:12:27 -040045 u32 *v = va_arg (*va, u32 *);
46 char *fmt = va_arg (*va, char *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070047 uword i;
48 for (i = 0; i < vec_len (v); i++)
49 {
50 if (i > 0)
51 s = format (s, ", ");
52 s = format (s, fmt, v[i]);
53 }
54 return s;
55}
56
Dave Barachc3799992016-08-15 11:12:27 -040057u8 *
58format_vec_uword (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -070059{
Dave Barachc3799992016-08-15 11:12:27 -040060 uword *v = va_arg (*va, uword *);
61 char *fmt = va_arg (*va, char *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070062 uword i;
63 for (i = 0; i < vec_len (v); i++)
64 {
65 if (i > 0)
66 s = format (s, ", ");
67 s = format (s, fmt, v[i]);
68 }
69 return s;
70}
71
72/* Ascii buffer and length. */
Dave Barachc3799992016-08-15 11:12:27 -040073u8 *
74format_ascii_bytes (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -070075{
Dave Barachc3799992016-08-15 11:12:27 -040076 u8 *v = va_arg (*va, u8 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070077 uword n_bytes = va_arg (*va, uword);
78 vec_add (s, v, n_bytes);
79 return s;
80}
81
82/* Format hex dump. */
Dave Barachc3799992016-08-15 11:12:27 -040083u8 *
84format_hex_bytes (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -070085{
Dave Barachc3799992016-08-15 11:12:27 -040086 u8 *bytes = va_arg (*va, u8 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070087 int n_bytes = va_arg (*va, int);
88 uword i;
89
90 /* Print short or long form depending on byte count. */
91 uword short_form = n_bytes <= 32;
Christophe Fontained3c008d2017-10-02 18:10:54 +020092 u32 indent = format_get_indent (s);
Ed Warnickecb9cada2015-12-08 15:45:58 -070093
94 if (n_bytes == 0)
95 return s;
96
97 for (i = 0; i < n_bytes; i++)
98 {
Dave Barachc3799992016-08-15 11:12:27 -040099 if (!short_form && (i % 32) == 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700100 s = format (s, "%08x: ", i);
101
102 s = format (s, "%02x", bytes[i]);
103
Dave Barachc3799992016-08-15 11:12:27 -0400104 if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700105 s = format (s, "\n%U", format_white_space, indent);
106 }
107
108 return s;
109}
110
Damjan Marion3860a772019-06-17 23:20:27 +0200111u8 *
112format_hex_bytes_no_wrap (u8 * s, va_list * va)
113{
114 u8 *bytes = va_arg (*va, u8 *);
115 int n_bytes = va_arg (*va, int);
116 uword i;
117
118 if (n_bytes == 0)
119 return s;
120
121 for (i = 0; i < n_bytes; i++)
122 s = format (s, "%02x", bytes[i]);
123
124 return s;
125}
126
Ed Warnickecb9cada2015-12-08 15:45:58 -0700127/* Add variable number of spaces. */
Dave Barachc3799992016-08-15 11:12:27 -0400128u8 *
129format_white_space (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700130{
Gabriel Gannee3ea7972017-10-12 10:53:31 +0200131 u32 n = va_arg (*va, u32);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700132 while (n-- > 0)
133 vec_add1 (s, ' ');
134 return s;
135}
136
Dave Barachc3799992016-08-15 11:12:27 -0400137u8 *
Nathan Skrzypczak6de58f52022-01-24 17:10:41 +0100138format_duration (u8 *s, va_list *args)
139{
140 f64 t = va_arg (*args, f64);
141 s = format (s, "");
142
143 const f64 seconds_per_minute = 60;
144 const f64 seconds_per_hour = 60 * seconds_per_minute;
145 const f64 seconds_per_day = 24 * seconds_per_hour;
146 uword days, hours, minutes, secs, msecs, usecs;
147
148 days = t / seconds_per_day;
149 t -= days * seconds_per_day;
150
151 hours = t / seconds_per_hour;
152 t -= hours * seconds_per_hour;
153
154 minutes = t / seconds_per_minute;
155 t -= minutes * seconds_per_minute;
156
157 secs = t;
158 t -= secs;
159
160 msecs = 1e3 * t;
161
162 usecs = 1e6 * t;
163 usecs = usecs % 1000;
164
165 if (t == 0.)
166 s = format (s, "0");
167 if (days)
168 s = format (s, "%ddays ", days);
169 if (hours)
170 s = format (s, "%dh ", hours);
171 if (minutes)
172 s = format (s, "%dmin ", minutes);
173 if (secs)
174 s = format (s, "%ds ", secs);
175 if (msecs)
176 s = format (s, "%dms ", msecs);
177 if (usecs)
178 s = format (s, "%dus", usecs);
179
180 return (s);
181}
182
183u8 *
Dave Barachc3799992016-08-15 11:12:27 -0400184format_time_interval (u8 * s, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700185{
Dave Barachc3799992016-08-15 11:12:27 -0400186 u8 *fmt = va_arg (*args, u8 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700187 f64 t = va_arg (*args, f64);
Dave Barachc3799992016-08-15 11:12:27 -0400188 u8 *f;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700189
190 const f64 seconds_per_minute = 60;
191 const f64 seconds_per_hour = 60 * seconds_per_minute;
192 const f64 seconds_per_day = 24 * seconds_per_hour;
193 uword days, hours, minutes, secs, msecs, usecs;
Dave Barachc3799992016-08-15 11:12:27 -0400194
Ed Warnickecb9cada2015-12-08 15:45:58 -0700195 days = t / seconds_per_day;
196 t -= days * seconds_per_day;
197
198 hours = t / seconds_per_hour;
199 t -= hours * seconds_per_hour;
200
201 minutes = t / seconds_per_minute;
202 t -= minutes * seconds_per_minute;
203
204 secs = t;
205 t -= secs;
206
Dave Barachc3799992016-08-15 11:12:27 -0400207 msecs = 1e3 * t;
208 usecs = 1e6 * t;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700209
210 for (f = fmt; *f; f++)
211 {
212 uword what, c;
Dave Barachc3799992016-08-15 11:12:27 -0400213 char *what_fmt = "%d";
Ed Warnickecb9cada2015-12-08 15:45:58 -0700214
215 switch (c = *f)
216 {
217 default:
218 vec_add1 (s, c);
219 continue;
220
221 case 'd':
222 what = days;
223 what_fmt = "%d";
224 break;
225 case 'h':
226 what = hours;
227 what_fmt = "%02d";
228 break;
229 case 'm':
230 what = minutes;
231 what_fmt = "%02d";
232 break;
233 case 's':
234 what = secs;
235 what_fmt = "%02d";
236 break;
237 case 'f':
238 what = msecs;
239 what_fmt = "%03d";
240 break;
241 case 'u':
242 what = usecs;
243 what_fmt = "%06d";
244 break;
245 }
246
247 s = format (s, what_fmt, what);
248 }
249
250 return s;
251}
252
Nathan Skrzypczak162ff5e2021-11-09 18:18:21 +0100253/* Format base 10 e.g. 100, 100K, 100M, 100G */
254__clib_export u8 *
255format_base10 (u8 *s, va_list *va)
256{
257 uword size = va_arg (*va, uword);
258
259 if (size < 1000)
260 s = format (s, "%d", size);
261 else if (size < 1000000)
262 s = format (s, "%.2fK", (f64) size / 1000.);
263 else if (size < 1000000000)
264 s = format (s, "%.2fM", (f64) size / 1000000.);
265 else
266 s = format (s, "%.2fG", (f64) size / 1000000000.);
267
268 return s;
269}
270
Ed Warnickecb9cada2015-12-08 15:45:58 -0700271/* Unparse memory size e.g. 100, 100k, 100m, 100g. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200272__clib_export u8 *
Dave Barachc3799992016-08-15 11:12:27 -0400273format_memory_size (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700274{
275 uword size = va_arg (*va, uword);
276 uword l, u, log_u;
277
278 l = size > 0 ? min_log2 (size) : 0;
279 if (l < 10)
280 log_u = 0;
281 else if (l < 20)
282 log_u = 10;
283 else if (l < 30)
284 log_u = 20;
285 else
286 log_u = 30;
287
288 u = (uword) 1 << log_u;
289 if (size & (u - 1))
290 s = format (s, "%.2f", (f64) size / (f64) u);
291 else
292 s = format (s, "%d", size >> log_u);
293
294 if (log_u != 0)
295 s = format (s, "%c", " kmg"[log_u / 10]);
296
297 return s;
298}
299
300/* Parse memory size e.g. 100, 100k, 100m, 100g. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200301__clib_export uword
Dave Barachc3799992016-08-15 11:12:27 -0400302unformat_memory_size (unformat_input_t * input, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700303{
304 uword amount, shift, c;
Dave Barachc3799992016-08-15 11:12:27 -0400305 uword *result = va_arg (*va, uword *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700306
Dave Barachc3799992016-08-15 11:12:27 -0400307 if (!unformat (input, "%wd%_", &amount))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700308 return 0;
309
310 c = unformat_get_input (input);
311 switch (c)
312 {
Dave Barachc3799992016-08-15 11:12:27 -0400313 case 'k':
314 case 'K':
315 shift = 10;
316 break;
317 case 'm':
318 case 'M':
319 shift = 20;
320 break;
321 case 'g':
322 case 'G':
323 shift = 30;
324 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700325 default:
326 shift = 0;
327 unformat_put_input (input);
328 break;
329 }
330
331 *result = amount << shift;
332 return 1;
333}
334
Damjan Marionb5095042020-09-11 22:13:46 +0200335/* Unparse memory page size e.g. 4K, 2M */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200336__clib_export u8 *
Damjan Marionb5095042020-09-11 22:13:46 +0200337format_log2_page_size (u8 * s, va_list * va)
338{
339 clib_mem_page_sz_t log2_page_sz = va_arg (*va, clib_mem_page_sz_t);
340
341 if (log2_page_sz == CLIB_MEM_PAGE_SZ_UNKNOWN)
342 return format (s, "unknown");
343
344 if (log2_page_sz == CLIB_MEM_PAGE_SZ_DEFAULT)
345 return format (s, "default");
346
347 if (log2_page_sz == CLIB_MEM_PAGE_SZ_DEFAULT_HUGE)
348 return format (s, "default-hugepage");
349
350 if (log2_page_sz >= 30)
351 return format (s, "%uG", 1 << (log2_page_sz - 30));
352
353 if (log2_page_sz >= 20)
354 return format (s, "%uM", 1 << (log2_page_sz - 20));
355
356 if (log2_page_sz >= 10)
357 return format (s, "%uK", 1 << (log2_page_sz - 10));
358
359 return format (s, "%u", 1 << log2_page_sz);
360}
361
362/* Parse memory page size e.g. 4K, 2M */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200363__clib_export uword
Damjan Marionb5095042020-09-11 22:13:46 +0200364unformat_log2_page_size (unformat_input_t * input, va_list * va)
365{
Nathan Skrzypczak61559022020-11-23 16:25:21 +0100366 uword amount;
Damjan Marionb5095042020-09-11 22:13:46 +0200367 clib_mem_page_sz_t *result = va_arg (*va, clib_mem_page_sz_t *);
368
Damjan Marionb5095042020-09-11 22:13:46 +0200369 if (unformat (input, "default-hugepage"))
Nathan Skrzypczak61559022020-11-23 16:25:21 +0100370 *result = CLIB_MEM_PAGE_SZ_DEFAULT_HUGE;
371 else if (unformat (input, "default"))
372 *result = CLIB_MEM_PAGE_SZ_DEFAULT;
373 else if (unformat (input, "%wdk", &amount))
374 *result = min_log2 (amount) + 10;
375 else if (unformat (input, "%wdK", &amount))
376 *result = min_log2 (amount) + 10;
377 else if (unformat (input, "%wdm", &amount))
378 *result = min_log2 (amount) + 20;
379 else if (unformat (input, "%wdM", &amount))
380 *result = min_log2 (amount) + 20;
381 else if (unformat (input, "%wdg", &amount))
382 *result = min_log2 (amount) + 30;
383 else if (unformat (input, "%wdG", &amount))
384 *result = min_log2 (amount) + 30;
385 else
386 return 0;
Damjan Marionb5095042020-09-11 22:13:46 +0200387 return 1;
388}
389
Ed Warnickecb9cada2015-12-08 15:45:58 -0700390/* Format c identifier: e.g. a_name -> "a name".
Klement Sekeraea841302018-05-11 12:59:05 +0200391 Works for both vector names and null terminated c strings. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200392__clib_export u8 *
Dave Barachc3799992016-08-15 11:12:27 -0400393format_c_identifier (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700394{
Dave Barachc3799992016-08-15 11:12:27 -0400395 u8 *id = va_arg (*va, u8 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700396 uword i, l;
397
398 l = ~0;
399 if (clib_mem_is_vec (id))
400 l = vec_len (id);
401
402 if (id)
BenoƮt Ganne1bd6f612020-07-16 12:03:35 +0200403 for (i = 0; i < l && id[i] != 0; i++)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700404 {
405 u8 c = id[i];
406
407 if (c == '_')
408 c = ' ';
409 vec_add1 (s, c);
410 }
411
412 return s;
413}
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200414
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200415__clib_export u8 *
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200416format_hexdump (u8 * s, va_list * args)
417{
Dave Barachc3799992016-08-15 11:12:27 -0400418 u8 *data = va_arg (*args, u8 *);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200419 uword len = va_arg (*args, uword);
Dave Barachc3799992016-08-15 11:12:27 -0400420 int i, index = 0;
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200421 const int line_len = 16;
Dave Barachc3799992016-08-15 11:12:27 -0400422 u8 *line_hex = 0;
423 u8 *line_str = 0;
Christophe Fontained3c008d2017-10-02 18:10:54 +0200424 u32 indent = format_get_indent (s);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200425
426 if (!len)
427 return s;
428
Dave Barachc3799992016-08-15 11:12:27 -0400429 for (i = 0; i < len; i++)
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200430 {
Dave Barachc3799992016-08-15 11:12:27 -0400431 line_hex = format (line_hex, "%02x ", data[i]);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200432 line_str = format (line_str, "%c", isprint (data[i]) ? data[i] : '.');
Dave Barachc3799992016-08-15 11:12:27 -0400433 if (!((i + 1) % line_len))
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200434 {
435 s = format (s, "%U%05x: %v[%v]",
436 format_white_space, index ? indent : 0,
437 index, line_hex, line_str);
438 if (i < len - 1)
439 s = format (s, "\n");
440 index = i + 1;
Dave Barachc3799992016-08-15 11:12:27 -0400441 vec_reset_length (line_hex);
442 vec_reset_length (line_str);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200443 }
444 }
445
446 while (i++ % line_len)
447 line_hex = format (line_hex, " ");
448
Dave Barachc3799992016-08-15 11:12:27 -0400449 if (vec_len (line_hex))
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200450 s = format (s, "%U%05x: %v[%v]",
Damjan Marion1e336632018-02-17 14:05:08 +0100451 format_white_space, index ? indent : 0,
452 index, line_hex, line_str);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200453
Dave Barachc3799992016-08-15 11:12:27 -0400454 vec_free (line_hex);
455 vec_free (line_str);
Damjan Mariona7e83ce2016-06-09 12:38:22 +0200456
457 return s;
458}
Dave Barachc3799992016-08-15 11:12:27 -0400459
Damjan Marione6387b22021-12-22 21:58:54 +0100460__clib_export u8 *
461format_u64_bitmap (u8 *s, va_list *args)
462{
463 u64 *bitmap = va_arg (*args, u64 *);
464 int n_uword = va_arg (*args, int);
465 u32 indent = format_get_indent (s);
466
467 s = format (s, "%6s", "");
468
469 for (int i = 60; i >= 0; i -= 4)
470 s = format (s, "%5d", i);
471
472 vec_add1 (s, '\n');
473
474 for (int j = n_uword - 1; j >= 0; j--)
475 {
476 s = format (s, "%U0x%04x ", format_white_space, indent, j * 8);
477 for (int i = 63; i >= 0; i--)
478 {
479 vec_add1 (s, (1ULL << i) & bitmap[j] ? '1' : '.');
480 if (i % 4 == 0)
481 vec_add1 (s, ' ');
482 }
483 s = format (s, "0x%016lx", bitmap[j]);
484 if (j)
485 vec_add1 (s, '\n');
486 }
487
488 return s;
489}
490
Dave Barachc3799992016-08-15 11:12:27 -0400491/*
492 * fd.io coding-style-patch-verification: ON
493 *
494 * Local Variables:
495 * eval: (c-set-style "gnu")
496 * End:
497 */