aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet
ModeNameSize
-rw-r--r--CMakeLists.txt35165logstatsplain
-rw-r--r--MTU.md2771logstatsplain
d---------adj893logstatsplain
-rw-r--r--api_errno.h10853logstatsplain
d---------arp295logstatsplain
d---------bfd532logstatsplain
d---------bier1576logstatsplain
d---------bonding251logstatsplain
-rw-r--r--buffer.c1902logstatsplain
-rw-r--r--buffer.h13905logstatsplain
d---------classify633logstatsplain
-rw-r--r--config.c10584logstatsplain
-rw-r--r--config.h5343logstatsplain
d---------cop299logstatsplain
d---------crypto141logstatsplain
d---------devices278logstatsplain
-rw-r--r--dir.dox973logstatsplain
d---------dpo1520logstatsplain
d---------ethernet999logstatsplain
d---------feature196logstatsplain
d---------fib2403logstatsplain
d---------flow106logstatsplain
-rw-r--r--format_fns.h794logstatsplain
d---------geneve307logstatsplain
-rw-r--r--global_funcs.h949logstatsplain
d---------gre356logstatsplain
d---------gso245logstatsplain
-rw-r--r--handoff.c8749logstatsplain
-rw-r--r--handoff.h6232logstatsplain
d---------hdlc207logstatsplain
-rw-r--r--interface.api18381logstatsplain
-rw-r--r--interface.c50203logstatsplain
-rw-r--r--interface.h31380logstatsplain
-rw-r--r--interface_api.c40831logstatsplain
-rw-r--r--interface_cli.c70514logstatsplain
-rw-r--r--interface_format.c22135logstatsplain
-rw-r--r--interface_funcs.h16134logstatsplain
-rw-r--r--interface_output.c31886logstatsplain
-rw-r--r--interface_output.h3504logstatsplain
-rw-r--r--interface_stats.c5606logstatsplain
-rw-r--r--interface_types.api1827logstatsplain
d---------ip-neighbor654logstatsplain
d---------ip3188logstatsplain
d---------ip6-nd528logstatsplain
d---------ipfix-export395logstatsplain
d---------ipip324logstatsplain
d---------ipsec1277logstatsplain
d---------l21680logstatsplain
d---------l2tp320logstatsplain
-rw-r--r--l3_types.h2206logstatsplain
d---------lawful-intercept126logstatsplain
d---------lisp-cp795logstatsplain
d---------lisp-gpe909logstatsplain
d---------llc132logstatsplain
d---------lldp462logstatsplain
d---------mfib1035logstatsplain
-rw-r--r--misc.c3682logstatsplain
d---------mpls654logstatsplain
d---------osi132logstatsplain
d---------pci127logstatsplain
d---------pg426logstatsplain
-rw-r--r--pipeline.h9871logstatsplain
d---------plugin36logstatsplain
d---------policer344logstatsplain
d---------ppp205logstatsplain
d---------qos644logstatsplain
d---------session1432logstatsplain
d---------snap134logstatsplain
d---------span215logstatsplain
d---------srmpls319logstatsplain
d---------srp210log.highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
-rw-r--r--vnet_all_api_h.h2731logstatsplain
-rw-r--r--vnet_msg_enum.h1028logstatsplain
d---------vxlan-gbp406logstatsplain
d---------vxlan-gpe445logstatsplain
d---------vxlan376logstatsplain
"n">buffer_marks[0]; /* Re-use buffer when no marks. */ if (first_mark > 0) vec_delete (i->buffer, first_mark, 0); i->index = vec_len (i->buffer); for (l = 0; l < vec_len (i->buffer_marks); l++) i->buffer_marks[l] -= first_mark; /* Call user's function to fill the buffer. */ if (i->fill_buffer) i->index = i->fill_buffer (i); /* If input pointer is still beyond end of buffer even after fill then we've run out of input. */ if (i->index >= vec_len (i->buffer)) i->index = UNFORMAT_END_OF_INPUT; return i->index; } always_inline uword is_white_space (uword c) { switch (c) { case ' ': case '\t': case '\n': case '\r': return 1; default: return 0; } } /* Format function for dumping input stream. */ __clib_export u8 * format_unformat_error (u8 * s, va_list * va) { unformat_input_t *i = va_arg (*va, unformat_input_t *); uword l = vec_len (i->buffer); /* Only show so much of the input buffer (it could be really large). */ uword n_max = 30; if (i->index < l) { uword n = l - i->index; u8 *p, *p_end; p = i->buffer + i->index; p_end = p + (n > n_max ? n_max : n); /* Skip white space at end. */ if (n <= n_max) { while (p_end > p && is_white_space (p_end[-1])) p_end--; } while (p < p_end) { switch (*p) { case '\r': vec_add (s, "\\r", 2); break; case '\n': vec_add (s, "\\n", 2); break; case '\t': vec_add (s, "\\t", 2); break; default: vec_add1 (s, *p); break; } p++; } if (n > n_max) vec_add (s, "...", 3); } return s; } /* Print everything: not just error context. */ __clib_export u8 * format_unformat_input (u8 * s, va_list * va) { unformat_input_t *i = va_arg (*va, unformat_input_t *); uword l, n; if (i->index == UNFORMAT_END_OF_INPUT) s = format (s, "{END_OF_INPUT}"); else { l = vec_len (i->buffer); n = l - i->index; if (n > 0) vec_add (s, i->buffer + i->index, n); } return s; } #if CLIB_DEBUG > 0 void di (unformat_input_t * i) { fformat (stderr, "%U\n", format_unformat_input, i); } #endif /* Parse delimited vector string. If string starts with { then string is delimited by balanced parenthesis. Other string is delimited by white space. {} were chosen since they are special to the shell. */ static uword unformat_string (unformat_input_t * input, uword delimiter_character, uword format_character, va_list * va) { u8 **string_return = va_arg (*va, u8 **); u8 *s = 0; word paren = 0; word is_paren_delimited = 0; word backslash = 0; uword c; switch (delimiter_character) { case '%': case ' ': case '\t': delimiter_character = 0; break; } while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) { word add_to_vector; /* Null return string means to skip over delimited input. */ add_to_vector = string_return != 0; if (backslash) backslash = 0; else switch (c) { case '\\': backslash = 1; add_to_vector = 0; break; case '{': if (paren == 0 && vec_len (s) == 0) { is_paren_delimited = 1; add_to_vector = 0; } paren++; break; case '}': paren--; if (is_paren_delimited && paren == 0) goto done; break; case ' ': case '\t': case '\n': case '\r': if (!is_paren_delimited) { unformat_put_input (input); goto done; } break; default: if (!is_paren_delimited && c == delimiter_character) { unformat_put_input (input); goto done; } } if (add_to_vector) vec_add1 (s, c); } done: if (string_return) { /* Match the string { END-OF-INPUT as a single brace. */ if (c == UNFORMAT_END_OF_INPUT && vec_len (s) == 0 && paren == 1) vec_add1 (s, '{'); /* Don't match null string. */ if (c == UNFORMAT_END_OF_INPUT && vec_len (s) == 0) return 0; /* Null terminate C string. */ if (format_character == 's') vec_add1 (s, 0); *string_return = s; } else vec_free (s); /* just to make sure */ return 1; } __clib_export uword unformat_hex_string (unformat_input_t * input, va_list * va) { u8 **hexstring_return = va_arg (*va, u8 **); u8 *s; uword n, d, c; n = 0; d = 0; s = 0; while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) { if (c >= '0' && c <= '9') d = 16 * d + c - '0'; else if (c >= 'a' && c <= 'f') d = 16 * d + 10 + c - 'a'; else if (c >= 'A' && c <= 'F') d = 16 * d + 10 + c - 'A'; else { unformat_put_input (input); break; } n++; if (n == 2) { vec_add1 (s, d); n = d = 0; } } /* Hex string must have even number of digits. */ if (n % 2) { vec_free (s); return 0; } /* Make sure something was processed. */ else if (s == 0) { return 0; } *hexstring_return = s; return 1; } /* unformat (input "foo%U", unformat_eof) matches terminal foo only */ __clib_export uword unformat_eof (unformat_input_t * input, va_list * va) { return unformat_check_input (input) == UNFORMAT_END_OF_INPUT; } /* Parse a token containing given set of characters. */ __clib_export uword unformat_token (unformat_input_t * input, va_list * va) { u8 *token_chars = va_arg (*va, u8 *); u8 **string_return = va_arg (*va, u8 **); u8 *s, map[256]; uword i, c; if (!token_chars) token_chars = (u8 *) "a-zA-Z0-9_"; clib_memset (map, 0, sizeof (map)); for (s = token_chars; *s;) { /* * Parse range. * The test order is important: s[1] is valid because s[0] != '\0' but * s[2] might not if s[1] == '\0' * Also, if s[1] == '-' but s[2] == '\0' the test s[0] < s[2] will * (correctly) fail */ if (s[1] == '-' && s[0] < s[2]) { for (i = s[0]; i <= s[2]; i++) map[i] = 1; s = s + 3; } else { map[s[0]] = 1; s = s + 1; } } s = 0; while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) { if (!map[c]) { unformat_put_input (input); break; } vec_add1 (s, c); } if (vec_len (s) == 0) return 0; *string_return = s; return 1; } /* Unformat (parse) function which reads a %s string and converts it to and unformat_input_t. */ __clib_export uword unformat_input (unformat_input_t * i, va_list * args) { unformat_input_t *sub_input = va_arg (*args, unformat_input_t *); u8 *s; if (unformat (i, "%v", &s)) { unformat_init_vector (sub_input, s); return 1; } return 0; } /* Parse a line ending with \n and return it. */ __clib_export uword unformat_line (unformat_input_t * i, va_list * va) { u8 *line = 0, **result = va_arg (*va, u8 **); uword c; while ((c = unformat_get_input (i)) != '\n' && c != UNFORMAT_END_OF_INPUT) { vec_add1 (line, c); } *result = line; return vec_len (line); } /* Parse a line ending with \n and return it as an unformat_input_t. */ __clib_export uword unformat_line_input (unformat_input_t * i, va_list * va) { unformat_input_t *result = va_arg (*va, unformat_input_t *); u8 *line; if (!unformat_user (i, unformat_line, &line)) return 0; unformat_init_vector (result, line); return 1; } /* Values for is_signed. */ #define UNFORMAT_INTEGER_SIGNED 1 #define UNFORMAT_INTEGER_UNSIGNED 0 static uword unformat_integer (unformat_input_t * input, va_list * va, uword base, uword is_signed, uword data_bytes) { uword c, digit; uword value = 0; uword n_digits = 0; uword n_input = 0; uword sign = 0; /* We only support bases <= 64. */ if (base < 2 || base > 64) goto error; while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) { switch (c) { case '-': if (n_input == 0) { if (is_signed) { sign = 1; goto next_digit; } else /* Leading sign for unsigned number. */ goto error; } /* Sign after input (e.g. 100-200). */ goto put_input_done; case '+': if (n_input > 0) goto put_input_done; sign = 0; goto next_digit; case '0' ... '9': digit = c - '0'; break; case 'a' ... 'z': digit = 10 + (c - 'a'); break; case 'A' ... 'Z': digit = 10 + (base >= 36 ? 26 : 0) + (c - 'A'); break; case '/': digit = 62; break; case '?': digit = 63; break; default: goto put_input_done; } if (digit >= base) { put_input_done: unformat_put_input (input); goto done; } { uword new_value = base * value + digit; /* Check for overflow. */ if (new_value < value) goto error; value = new_value; } n_digits += 1; next_digit: n_input++; } done: if (sign) value = -value; if (n_digits > 0) { void *v = va_arg (*va, void *); if (data_bytes == ~0) data_bytes = sizeof (int); switch (data_bytes) { case 1: *(u8 *) v = value; break; case 2: *(u16 *) v = value; break; case 4: *(u32 *) v = value; break; case 8: *(u64 *) v = value; break; default: goto error; } return 1; } error: return 0; } /* Return x 10^n */ static f64 times_power_of_ten (f64 x, int n) { if (n >= 0) { static f64 t[8] = { 1e+0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, }; while (n >= 8) { x *= 1e+8; n -= 8; } return x * t[n]; } else { static f64 t[8] = { 1e-0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, }; while (n <= -8) { x *= 1e-8; n += 8; } return x * t[-n]; } } static uword unformat_float (unformat_input_t * input, va_list * va) { uword c; u64 values[3]; uword n_digits[3], value_index = 0; uword signs[2], sign_index = 0; uword n_input = 0; clib_memset (values, 0, sizeof (values)); clib_memset (n_digits, 0, sizeof (n_digits)); clib_memset (signs, 0, sizeof (signs)); while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) { switch (c) { case '-': if (value_index == 2 && n_digits[2] == 0) /* sign of exponent: it's ok. */ ; else if (value_index < 2 && n_digits[0] > 0) { /* 123- */ unformat_put_input (input); goto done; } else if (n_input > 0) goto error; signs[sign_index++] = 1; goto next_digit; case '+': if (value_index == 2 && n_digits[2] == 0) /* sign of exponent: it's ok. */ ; else if (value_index < 2 && n_digits[0] > 0) { /* 123+ */ unformat_put_input (input); goto done; } else if (n_input > 0) goto error; signs[sign_index++] = 0; goto next_digit; case 'e': case 'E': if (n_input == 0) goto error; value_index = 2; sign_index = 1; break; case '.': if (value_index > 0) goto error; value_index = 1; break; case '0' ... '9': { u64 tmp; tmp = values[value_index] * 10 + c - '0'; /* Check for overflow. */ if (tmp < values[value_index]) goto error; values[value_index] = tmp; n_digits[value_index] += 1; } break; default: unformat_put_input (input); goto done; } next_digit: n_input++; } done: { f64 f_values[2], *value_return; word expon; /* Must have either whole or fraction digits. */ if (n_digits[0] + n_digits[1] <= 0) goto error; f_values[0] = values[0]; if (signs[0]) f_values[0] = -f_values[0]; f_values[1] = values[1]; f_values[1] = times_power_of_ten (f_values[1], -n_digits[1]); f_values[0] += f_values[1]; expon = values[2]; if (signs[1]) expon = -expon; f_values[0] = times_power_of_ten (f_values[0], expon); value_return = va_arg (*va, f64 *); *value_return = f_values[0]; return 1; } error: return 0; } static const char * match_input_with_format (unformat_input_t * input, const char *f) { uword cf, ci; ASSERT (*f != 0); while (1) { cf = *f; if (cf == 0 || cf == '%' || cf == ' ') break; f++; ci = unformat_get_input (input); if (cf != ci) return 0; } return f; } static const char * do_percent (unformat_input_t * input, va_list * va, const char *f) { uword cf, n, data_bytes = ~0; cf = *f++; switch (cf) { default: break; case 'w': /* Word types. */ cf = *f++; data_bytes = sizeof (uword); break; case 'l': cf = *f++; if (cf == 'l') { cf = *f++; data_bytes = sizeof (long long); } else { data_bytes = sizeof (long); } break; case 'L': cf = *f++; data_bytes = sizeof (long long); break; } n = 0; switch (cf) { case 'D': data_bytes = va_arg (*va, int); case 'd': n = unformat_integer (input, va, 10, UNFORMAT_INTEGER_SIGNED, data_bytes); break; case 'u': n = unformat_integer (input, va, 10, UNFORMAT_INTEGER_UNSIGNED, data_bytes); break; case 'b': n = unformat_integer (input, va, 2, UNFORMAT_INTEGER_UNSIGNED, data_bytes); break; case 'o': n = unformat_integer (input, va, 8, UNFORMAT_INTEGER_UNSIGNED, data_bytes); break; case 'X': data_bytes = va_arg (*va, int); case 'x': n = unformat_integer (input, va, 16, UNFORMAT_INTEGER_UNSIGNED, data_bytes); break; case 'f': n = unformat_float (input, va); break; case 's': case 'v': n = unformat_string (input, f[0], cf, va); break; case 'U': { unformat_function_t *f = va_arg (*va, unformat_function_t *); n = f (input, va); } break; case '=': case '|': { int *var = va_arg (*va, int *); uword val = va_arg (*va, int); if (cf == '|') val |= *var; *var = val; n = 1; } break; } return n ? f : 0; } __clib_export uword unformat_skip_white_space (unformat_input_t * input) { uword n = 0; uword c; while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) { if (!is_white_space (c)) { unformat_put_input (input); break; } n++; } return n; } __clib_export uword va_unformat (unformat_input_t * input, const char *fmt, va_list * va) { const char *f; uword input_matches_format; uword default_skip_input_white_space; uword n_input_white_space_skipped; uword last_non_white_space_match_percent; uword last_non_white_space_match_format; vec_add1_aligned (input->buffer_marks, input->index, sizeof (input->buffer_marks[0])); f = fmt; default_skip_input_white_space = 1; input_matches_format = 0; last_non_white_space_match_percent = 0; last_non_white_space_match_format = 0; while (1) { char cf; uword is_percent, skip_input_white_space; cf = *f; is_percent = 0; /* Always skip input white space at start of format string. Otherwise use default skip value which can be changed by %_ (see below). */ skip_input_white_space = f == fmt || default_skip_input_white_space; /* Spaces in format request skipping input white space. */ if (is_white_space (cf)) { skip_input_white_space = 1; /* Multiple format spaces are equivalent to a single white space. */ while (is_white_space (*++f)) ; } else if (cf == '%') { /* %_ toggles whether or not to skip input white space. */ switch (*++f) { case '_': default_skip_input_white_space = !default_skip_input_white_space; f++; /* For transition from skip to no-skip in middle of format string, skip input white space. For example, the following matches: fmt = "%_%d.%d%_->%_%d.%d%_" input "1.2 -> 3.4" Without this the space after -> does not get skipped. */ if (!default_skip_input_white_space && !(f == fmt + 2 || *f == 0)) unformat_skip_white_space (input); continue; /* %% means match % */ case '%': break; /* % at end of format string. */ case 0: goto parse_fail; default: is_percent = 1; break; } } n_input_white_space_skipped = 0; if (skip_input_white_space) n_input_white_space_skipped = unformat_skip_white_space (input); /* End of format string. */ if (cf == 0) { /* Force parse error when format string ends and input is not white or at end. As an example, this is to prevent format "foo" from matching input "food". The last_non_white_space_match_percent is to make "foo %d" match input "foo 10,bletch" with %d matching 10. */ if (skip_input_white_space && !last_non_white_space_match_percent && !last_non_white_space_match_format && n_input_white_space_skipped == 0 && input->index != UNFORMAT_END_OF_INPUT) goto parse_fail; break; } last_non_white_space_match_percent = is_percent; last_non_white_space_match_format = 0; /* Explicit spaces in format must match input white space. */ if (cf == ' ' && !default_skip_input_white_space) { if (n_input_white_space_skipped == 0) goto parse_fail; } else if (is_percent) { if (!(f = do_percent (input, va, f))) goto parse_fail; } else { const char *g = match_input_with_format (input, f); if (!g) goto parse_fail; last_non_white_space_match_format = g > f; f = g; } } input_matches_format = 1; parse_fail: /* Rewind buffer marks. */ { uword l = vec_len (input->buffer_marks); /* If we did not match back up buffer to last mark. */ if (!input_matches_format) input->index = input->buffer_marks[l - 1]; _vec_len (input->buffer_marks) = l - 1; } return input_matches_format; } __clib_export uword unformat (unformat_input_t * input, const char *fmt, ...) { va_list va; uword result; va_start (va, fmt); result = va_unformat (input, fmt, &va); va_end (va); return result; } __clib_export uword unformat_user (unformat_input_t * input, unformat_function_t * func, ...) { va_list va; uword result, l; /* Save place in input buffer in case parse fails. */ l = vec_len (input->buffer_marks); vec_add1_aligned (input->buffer_marks, input->index, sizeof (input->buffer_marks[0])); va_start (va, func); result = func (input, &va); va_end (va); if (!result && input->index != UNFORMAT_END_OF_INPUT) input->index = input->buffer_marks[l]; _vec_len (input->buffer_marks) = l; return result; } /* Setup for unformat of Unix style command line. */ __clib_export void unformat_init_command_line (unformat_input_t * input, char *argv[]) { uword i; unformat_init (input, 0, 0); /* Concatenate argument strings with space in between. */ for (i = 1; argv[i]; i++) { vec_add (input->buffer, argv[i], strlen (argv[i])); if (argv[i + 1]) vec_add1 (input->buffer, ' '); } } __clib_export void unformat_init_string (unformat_input_t * input, char *string, int string_len) { unformat_init (input, 0, 0); if (string_len > 0) vec_add (input->buffer, string, string_len); } __clib_export void unformat_init_vector (unformat_input_t * input, u8 * vector_string) { unformat_init (input, 0, 0); input->buffer = vector_string; } #ifdef CLIB_UNIX static uword clib_file_fill_buffer (unformat_input_t * input) { int fd = pointer_to_uword (input->fill_buffer_arg); uword l, n; l = vec_len (input->buffer); vec_resize (input->buffer, 4096); n = read (fd, input->buffer + l, 4096); if (n > 0) _vec_len (input->buffer) = l + n; if (n <= 0) return UNFORMAT_END_OF_INPUT; else return input->index; } __clib_export void unformat_init_clib_file (unformat_input_t * input, int file_descriptor) { unformat_init (input, clib_file_fill_buffer, uword_to_pointer (file_descriptor, void *)); } /* Take input from Unix environment variable. */ uword unformat_init_unix_env (unformat_input_t * input, char *var) { char *val = getenv (var); if (val) unformat_init_string (input, val, strlen (val)); return val != 0; } __clib_export uword unformat_data_size (unformat_input_t * input, va_list * args) { u64 _a; u64 *a = va_arg (*args, u64 *); if (unformat (input, "%lluGb", &_a)) *a = _a << 30; else if (unformat (input, "%lluG", &_a)) *a = _a << 30; else if (unformat (input, "%lluMb", &_a)) *a = _a << 20; else if (unformat (input, "%lluM", &_a)) *a = _a << 20; else if (unformat (input, "%lluKb", &_a)) *a = _a << 10; else if (unformat (input, "%lluK", &_a)) *a = _a << 10; else if (unformat (input, "%llu", a)) ; else return 0; return 1; } #endif /* CLIB_UNIX */ /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */