FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
std-formats.c
Go to the documentation of this file.
1 /*
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>
39 #include <ctype.h>
40 
41 /* Format vectors. */
42 u8 *
43 format_vec32 (u8 * s, va_list * va)
44 {
45  u32 *v = va_arg (*va, u32 *);
46  char *fmt = va_arg (*va, char *);
47  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 
57 u8 *
58 format_vec_uword (u8 * s, va_list * va)
59 {
60  uword *v = va_arg (*va, uword *);
61  char *fmt = va_arg (*va, char *);
62  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. */
73 u8 *
74 format_ascii_bytes (u8 * s, va_list * va)
75 {
76  u8 *v = va_arg (*va, u8 *);
77  uword n_bytes = va_arg (*va, uword);
78  vec_add (s, v, n_bytes);
79  return s;
80 }
81 
82 /* Format hex dump. */
83 u8 *
84 format_hex_bytes (u8 * s, va_list * va)
85 {
86  u8 *bytes = va_arg (*va, u8 *);
87  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;
92  u32 indent = format_get_indent (s);
93 
94  if (n_bytes == 0)
95  return s;
96 
97  for (i = 0; i < n_bytes; i++)
98  {
99  if (!short_form && (i % 32) == 0)
100  s = format (s, "%08x: ", i);
101 
102  s = format (s, "%02x", bytes[i]);
103 
104  if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
105  s = format (s, "\n%U", format_white_space, indent);
106  }
107 
108  return s;
109 }
110 
111 u8 *
112 format_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 
127 /* Add variable number of spaces. */
128 u8 *
129 format_white_space (u8 * s, va_list * va)
130 {
131  u32 n = va_arg (*va, u32);
132  while (n-- > 0)
133  vec_add1 (s, ' ');
134  return s;
135 }
136 
137 u8 *
138 format_time_interval (u8 * s, va_list * args)
139 {
140  u8 *fmt = va_arg (*args, u8 *);
141  f64 t = va_arg (*args, f64);
142  u8 *f;
143 
144  const f64 seconds_per_minute = 60;
145  const f64 seconds_per_hour = 60 * seconds_per_minute;
146  const f64 seconds_per_day = 24 * seconds_per_hour;
147  uword days, hours, minutes, secs, msecs, usecs;
148 
149  days = t / seconds_per_day;
150  t -= days * seconds_per_day;
151 
152  hours = t / seconds_per_hour;
153  t -= hours * seconds_per_hour;
154 
155  minutes = t / seconds_per_minute;
156  t -= minutes * seconds_per_minute;
157 
158  secs = t;
159  t -= secs;
160 
161  msecs = 1e3 * t;
162  usecs = 1e6 * t;
163 
164  for (f = fmt; *f; f++)
165  {
166  uword what, c;
167  char *what_fmt = "%d";
168 
169  switch (c = *f)
170  {
171  default:
172  vec_add1 (s, c);
173  continue;
174 
175  case 'd':
176  what = days;
177  what_fmt = "%d";
178  break;
179  case 'h':
180  what = hours;
181  what_fmt = "%02d";
182  break;
183  case 'm':
184  what = minutes;
185  what_fmt = "%02d";
186  break;
187  case 's':
188  what = secs;
189  what_fmt = "%02d";
190  break;
191  case 'f':
192  what = msecs;
193  what_fmt = "%03d";
194  break;
195  case 'u':
196  what = usecs;
197  what_fmt = "%06d";
198  break;
199  }
200 
201  s = format (s, what_fmt, what);
202  }
203 
204  return s;
205 }
206 
207 /* Unparse memory size e.g. 100, 100k, 100m, 100g. */
208 __clib_export u8 *
209 format_memory_size (u8 * s, va_list * va)
210 {
211  uword size = va_arg (*va, uword);
212  uword l, u, log_u;
213 
214  l = size > 0 ? min_log2 (size) : 0;
215  if (l < 10)
216  log_u = 0;
217  else if (l < 20)
218  log_u = 10;
219  else if (l < 30)
220  log_u = 20;
221  else
222  log_u = 30;
223 
224  u = (uword) 1 << log_u;
225  if (size & (u - 1))
226  s = format (s, "%.2f", (f64) size / (f64) u);
227  else
228  s = format (s, "%d", size >> log_u);
229 
230  if (log_u != 0)
231  s = format (s, "%c", " kmg"[log_u / 10]);
232 
233  return s;
234 }
235 
236 /* Parse memory size e.g. 100, 100k, 100m, 100g. */
237 __clib_export uword
238 unformat_memory_size (unformat_input_t * input, va_list * va)
239 {
240  uword amount, shift, c;
241  uword *result = va_arg (*va, uword *);
242 
243  if (!unformat (input, "%wd%_", &amount))
244  return 0;
245 
246  c = unformat_get_input (input);
247  switch (c)
248  {
249  case 'k':
250  case 'K':
251  shift = 10;
252  break;
253  case 'm':
254  case 'M':
255  shift = 20;
256  break;
257  case 'g':
258  case 'G':
259  shift = 30;
260  break;
261  default:
262  shift = 0;
263  unformat_put_input (input);
264  break;
265  }
266 
267  *result = amount << shift;
268  return 1;
269 }
270 
271 /* Unparse memory page size e.g. 4K, 2M */
272 __clib_export u8 *
273 format_log2_page_size (u8 * s, va_list * va)
274 {
275  clib_mem_page_sz_t log2_page_sz = va_arg (*va, clib_mem_page_sz_t);
276 
277  if (log2_page_sz == CLIB_MEM_PAGE_SZ_UNKNOWN)
278  return format (s, "unknown");
279 
280  if (log2_page_sz == CLIB_MEM_PAGE_SZ_DEFAULT)
281  return format (s, "default");
282 
283  if (log2_page_sz == CLIB_MEM_PAGE_SZ_DEFAULT_HUGE)
284  return format (s, "default-hugepage");
285 
286  if (log2_page_sz >= 30)
287  return format (s, "%uG", 1 << (log2_page_sz - 30));
288 
289  if (log2_page_sz >= 20)
290  return format (s, "%uM", 1 << (log2_page_sz - 20));
291 
292  if (log2_page_sz >= 10)
293  return format (s, "%uK", 1 << (log2_page_sz - 10));
294 
295  return format (s, "%u", 1 << log2_page_sz);
296 }
297 
298 /* Parse memory page size e.g. 4K, 2M */
299 __clib_export uword
301 {
302  uword amount;
303  clib_mem_page_sz_t *result = va_arg (*va, clib_mem_page_sz_t *);
304 
305  if (unformat (input, "default-hugepage"))
307  else if (unformat (input, "default"))
308  *result = CLIB_MEM_PAGE_SZ_DEFAULT;
309  else if (unformat (input, "%wdk", &amount))
310  *result = min_log2 (amount) + 10;
311  else if (unformat (input, "%wdK", &amount))
312  *result = min_log2 (amount) + 10;
313  else if (unformat (input, "%wdm", &amount))
314  *result = min_log2 (amount) + 20;
315  else if (unformat (input, "%wdM", &amount))
316  *result = min_log2 (amount) + 20;
317  else if (unformat (input, "%wdg", &amount))
318  *result = min_log2 (amount) + 30;
319  else if (unformat (input, "%wdG", &amount))
320  *result = min_log2 (amount) + 30;
321  else
322  return 0;
323  return 1;
324 }
325 
326 /* Format c identifier: e.g. a_name -> "a name".
327  Works for both vector names and null terminated c strings. */
328 __clib_export u8 *
329 format_c_identifier (u8 * s, va_list * va)
330 {
331  u8 *id = va_arg (*va, u8 *);
332  uword i, l;
333 
334  l = ~0;
335  if (clib_mem_is_vec (id))
336  l = vec_len (id);
337 
338  if (id)
339  for (i = 0; i < l && id[i] != 0; i++)
340  {
341  u8 c = id[i];
342 
343  if (c == '_')
344  c = ' ';
345  vec_add1 (s, c);
346  }
347 
348  return s;
349 }
350 
351 __clib_export u8 *
352 format_hexdump (u8 * s, va_list * args)
353 {
354  u8 *data = va_arg (*args, u8 *);
355  uword len = va_arg (*args, uword);
356  int i, index = 0;
357  const int line_len = 16;
358  u8 *line_hex = 0;
359  u8 *line_str = 0;
360  u32 indent = format_get_indent (s);
361 
362  if (!len)
363  return s;
364 
365  for (i = 0; i < len; i++)
366  {
367  line_hex = format (line_hex, "%02x ", data[i]);
368  line_str = format (line_str, "%c", isprint (data[i]) ? data[i] : '.');
369  if (!((i + 1) % line_len))
370  {
371  s = format (s, "%U%05x: %v[%v]",
372  format_white_space, index ? indent : 0,
373  index, line_hex, line_str);
374  if (i < len - 1)
375  s = format (s, "\n");
376  index = i + 1;
377  vec_reset_length (line_hex);
378  vec_reset_length (line_str);
379  }
380  }
381 
382  while (i++ % line_len)
383  line_hex = format (line_hex, " ");
384 
385  if (vec_len (line_hex))
386  s = format (s, "%U%05x: %v[%v]",
387  format_white_space, index ? indent : 0,
388  index, line_hex, line_str);
389 
390  vec_free (line_hex);
391  vec_free (line_str);
392 
393  return s;
394 }
395 
396 /*
397  * fd.io coding-style-patch-verification: ON
398  *
399  * Local Variables:
400  * eval: (c-set-style "gnu")
401  * End:
402  */
vec_reset_length
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
Definition: vec_bootstrap.h:194
vec_add
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:688
clib_mem_is_vec
static uword clib_mem_is_vec(void *v)
Predicate function, says whether the supplied vector is a clib heap object.
Definition: vec.h:244
unformat_log2_page_size
__clib_export uword unformat_log2_page_size(unformat_input_t *input, va_list *va)
Definition: std-formats.c:300
CLIB_MEM_PAGE_SZ_DEFAULT_HUGE
@ CLIB_MEM_PAGE_SZ_DEFAULT_HUGE
Definition: mem.h:61
f
vlib_frame_t * f
Definition: interface_output.c:1098
format_hex_bytes
u8 * format_hex_bytes(u8 *s, va_list *va)
Definition: std-formats.c:84
format_log2_page_size
__clib_export u8 * format_log2_page_size(u8 *s, va_list *va)
Definition: std-formats.c:273
unformat_input_t
struct _unformat_input_t unformat_input_t
format_hex_bytes_no_wrap
u8 * format_hex_bytes_no_wrap(u8 *s, va_list *va)
Definition: std-formats.c:112
unformat
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
unformat_put_input
static void unformat_put_input(unformat_input_t *input)
Definition: format.h:197
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
len
u8 len
Definition: ip_types.api:103
vec_add1
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:606
c
svmdb_client_t * c
Definition: vpp_get_metrics.c:48
uword
u64 uword
Definition: types.h:112
format_hexdump
__clib_export u8 * format_hexdump(u8 *s, va_list *args)
Definition: std-formats.c:352
format_c_identifier
__clib_export u8 * format_c_identifier(u8 *s, va_list *va)
Definition: std-formats.c:329
f64
double f64
Definition: types.h:142
format_time_interval
u8 * format_time_interval(u8 *s, va_list *args)
Definition: std-formats.c:138
format.h
unformat_get_input
static uword unformat_get_input(unformat_input_t *input)
Definition: format.h:184
fmt
int cJSON_bool fmt
Definition: cJSON.h:160
data
u8 data[128]
Definition: ipsec_types.api:95
vec_free
#define vec_free(V)
Free vector's memory (no header).
Definition: vec.h:395
size
u32 size
Definition: vhost_user.h:125
index
u32 index
Definition: flow_types.api:221
format
description fragment has unexpected format
Definition: map.api:433
format_get_indent
static u32 format_get_indent(u8 *s)
Definition: format.h:72
u32
unsigned int u32
Definition: types.h:88
CLIB_MEM_PAGE_SZ_DEFAULT
@ CLIB_MEM_PAGE_SZ_DEFAULT
Definition: mem.h:60
n_bytes
u32 n_bytes
Definition: interface_output.c:421
unformat_memory_size
__clib_export uword unformat_memory_size(unformat_input_t *input, va_list *va)
Definition: std-formats.c:238
format_vec32
u8 * format_vec32(u8 *s, va_list *va)
Definition: std-formats.c:43
format_memory_size
__clib_export u8 * format_memory_size(u8 *s, va_list *va)
Definition: std-formats.c:209
clib_mem_page_sz_t
clib_mem_page_sz_t
Definition: mem.h:57
u8
unsigned char u8
Definition: types.h:56
i
int i
Definition: flowhash_template.h:376
format_vec_uword
u8 * format_vec_uword(u8 *s, va_list *va)
Definition: std-formats.c:58
min_log2
static uword min_log2(uword x)
Definition: clib.h:176
CLIB_MEM_PAGE_SZ_UNKNOWN
@ CLIB_MEM_PAGE_SZ_UNKNOWN
Definition: mem.h:59
format_ascii_bytes
u8 * format_ascii_bytes(u8 *s, va_list *va)
Definition: std-formats.c:74
format_white_space
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129