diff options
Diffstat (limited to 'src/examples/vlib/plex_test.c')
-rw-r--r-- | src/examples/vlib/plex_test.c | 527 |
1 files changed, 527 insertions, 0 deletions
diff --git a/src/examples/vlib/plex_test.c b/src/examples/vlib/plex_test.c new file mode 100644 index 00000000000..ce0c8ef1141 --- /dev/null +++ b/src/examples/vlib/plex_test.c @@ -0,0 +1,527 @@ +/* + * Copyright (c) 2015 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <vlib/parse.h> +#include <vlib/unix/unix.h> + +static u8 * +format_value_v4_address (u8 * s, va_list * args) +{ + vlib_parse_value_t *v = va_arg (*args, vlib_parse_value_t *); + u32 a = v->value.as_uword; + + s = format (s, "%d.%d.%d.%d", + (a >> 24) & 0xFF, + (a >> 16) & 0xFF, (a >> 8) & 0xFF, (a >> 0) & 0xFF); + + return s; +} + +static vlib_parse_match_t +v4_address_match (vlib_parse_main_t * pm, vlib_parse_type_t * type, + vlib_lex_token_t * t, vlib_parse_value_t * valuep) +{ + u32 digit; + u32 value = 0; + int i; + + if (vec_len (pm->tokens) - (t - pm->tokens) < 7) + return VLIB_PARSE_MATCH_FAIL; + + /* NUMBER DOT NUMBER DOT NUMBER DOT NUMBER */ + + for (i = 0; i < 7; i++) + { + if ((i & 1) == 0) + { + if (t[i].token != VLIB_LEX_number) + return VLIB_PARSE_MATCH_FAIL; + if (t[i].value.as_uword > 0xff) + return VLIB_PARSE_MATCH_FAIL; + digit = t[i].value.as_uword; + value = (value << 8) | digit; + } + else + { + if (t[i].token != VLIB_LEX_dot) + return VLIB_PARSE_MATCH_FAIL; + } + } + /* note: caller advances by 1 */ + pm->current_token_index += 6; + valuep->value.as_uword = value; + return VLIB_PARSE_MATCH_VALUE; +} + +PARSE_TYPE_INIT (v4_address, v4_address_match, 0, format_value_v4_address) + static u8 *format_value_v4_address_and_mask (u8 * s, va_list * args) +{ + vlib_parse_value_t *v = va_arg (*args, vlib_parse_value_t *); + u32 *a = v->value.as_pointer; + + s = format (s, "%d.%d.%d.%d", + (a[0] >> 24) & 0xFF, + (a[0] >> 16) & 0xFF, (a[0] >> 8) & 0xFF, (a[0] >> 0) & 0xFF); + s = format (s, "/%d", a[1]); + + return s; +} + +static vlib_parse_match_t +v4_address_and_mask_match (vlib_parse_main_t * pm, vlib_parse_type_t * type, + vlib_lex_token_t * t, vlib_parse_value_t * valuep) +{ + u32 digit; + u32 address = 0; + u32 *rv = 0; + int i; + + if (vec_len (pm->tokens) - (t - pm->tokens) < 9) + return VLIB_PARSE_MATCH_FAIL; + + /* NUMBER DOT NUMBER DOT NUMBER DOT NUMBER */ + + for (i = 0; i < 7; i++) + { + if ((i & 1) == 0) + { + if (t[i].token != VLIB_LEX_number) + return VLIB_PARSE_MATCH_FAIL; + if (t[i].value.as_uword > 0xff) + return VLIB_PARSE_MATCH_FAIL; + digit = t[i].value.as_uword; + address = (address << 8) | digit; + } + else + { + if (t[i].token != VLIB_LEX_dot) + return VLIB_PARSE_MATCH_FAIL; + } + } + + if (t[7].token != VLIB_LEX_slash || t[8].token != VLIB_LEX_number) + return VLIB_PARSE_MATCH_FAIL; + + vec_add1 (rv, address); + vec_add1 (rv, t[8].value.as_uword); + + /* note: caller advances by 1 */ + pm->current_token_index += 8; + valuep->value.as_pointer = rv; + return VLIB_PARSE_MATCH_VALUE; +} + +void +v4_address_and_mask_cleanup (vlib_parse_value_t * valuep) +{ + u32 *trash = valuep->value.as_pointer; + vec_free (trash); +} + +PARSE_TYPE_INIT (v4_address_and_mask, v4_address_and_mask_match, + v4_address_and_mask_cleanup, + format_value_v4_address_and_mask) + vlib_lex_main_t vlib_lex_main; + + + + vlib_parse_match_t eval_factor0 (vlib_parse_main_t * pm, + vlib_parse_item_t * item, + vlib_parse_value_t * value) +{ + clib_warning ("%U", format_vlib_parse_value, pm); + return VLIB_PARSE_MATCH_RULE; +} + +vlib_parse_match_t +eval_factor1 (vlib_parse_main_t * pm, + vlib_parse_item_t * item, vlib_parse_value_t * value) +{ + clib_warning ("%U", format_vlib_parse_value, pm); + return VLIB_PARSE_MATCH_RULE; +} + +vlib_parse_match_t +eval_factor2 (vlib_parse_main_t * pm, + vlib_parse_item_t * item, vlib_parse_value_t * value) +{ + word a; + int index = vec_len (pm->parse_value) - 1; + + a = pm->parse_value[index].value.as_word; + + pm->parse_value[index].value.as_word = -a; + return VLIB_PARSE_MATCH_RULE; +} + +vlib_parse_match_t +eval_term0 (vlib_parse_main_t * pm, + vlib_parse_item_t * item, vlib_parse_value_t * value) +{ + clib_warning ("%U", format_vlib_parse_value, pm); + return VLIB_PARSE_MATCH_RULE; +} + +vlib_parse_match_t +eval_term1 (vlib_parse_main_t * pm, + vlib_parse_item_t * item, vlib_parse_value_t * value) +{ + uword a, b; + int index = vec_len (pm->parse_value) - 2; + + a = pm->parse_value[index].value.as_uword; + b = pm->parse_value[index + 1].value.as_uword; + + pm->parse_value[index].value.as_uword = a * b; + _vec_len (pm->parse_value) -= 1; + clib_warning ("%U", format_vlib_parse_value, pm); + + return VLIB_PARSE_MATCH_RULE; +} + +vlib_parse_match_t +eval_term2 (vlib_parse_main_t * pm, + vlib_parse_item_t * item, vlib_parse_value_t * value) +{ + uword a, b; + int index = vec_len (pm->parse_value) - 2; + + a = pm->parse_value[index].value.as_uword; + b = pm->parse_value[index + 1].value.as_uword; + + pm->parse_value[index].value.as_uword = a / b; + _vec_len (pm->parse_value) -= 1; + clib_warning ("%U", format_vlib_parse_value, pm); + + return VLIB_PARSE_MATCH_RULE; +} + +vlib_parse_match_t +eval_exp0 (vlib_parse_main_t * pm, + vlib_parse_item_t * item, vlib_parse_value_t * value) +{ + return VLIB_PARSE_MATCH_RULE; +} + +vlib_parse_match_t +eval_exp1 (vlib_parse_main_t * pm, + vlib_parse_item_t * item, vlib_parse_value_t * value) +{ + uword a, b; + int index = vec_len (pm->parse_value) - 2; + + a = pm->parse_value[index].value.as_uword; + b = pm->parse_value[index + 1].value.as_uword; + + pm->parse_value[index].value.as_uword = a + b; + _vec_len (pm->parse_value) -= 1; + clib_warning ("%U", format_vlib_parse_value, pm); + + return VLIB_PARSE_MATCH_RULE; +} + +vlib_parse_match_t +eval_exp2 (vlib_parse_main_t * pm, + vlib_parse_item_t * item, vlib_parse_value_t * value) +{ + uword a, b; + int index = vec_len (pm->parse_value) - 2; + + a = pm->parse_value[index].value.as_uword; + b = pm->parse_value[index + 1].value.as_uword; + + pm->parse_value[index].value.as_uword = a - b; + _vec_len (pm->parse_value) -= 1; + clib_warning ("%U", format_vlib_parse_value, pm); + + return VLIB_PARSE_MATCH_RULE; +} + +vlib_parse_match_t +eval_result (vlib_parse_main_t * pm, + vlib_parse_item_t * item, vlib_parse_value_t * value) +{ + clib_warning ("%U", format_vlib_parse_value, pm); + return VLIB_PARSE_MATCH_DONE; +} + +vlib_parse_match_t +noop_match_rule (vlib_parse_main_t * pm, + vlib_parse_item_t * item, vlib_parse_value_t * value) +{ + clib_warning ("%U", format_vlib_parse_value, pm); + return VLIB_PARSE_MATCH_RULE; +} + +#if 0 +PARSE_INIT (t1, "moo", eval0); +PARSE_INIT (t2, "moo cow mumble", eval1); +PARSE_INIT (t3, "moo cow", eval2); +PARSE_INIT (t4, "moo cow mumble grunch", eval3); +#endif + +#if 0 +PARSE_INIT (r1, "eval <exp>", eval_result); + +PARSE_INIT (r2, "<exp> = <term><exp2>", eval_exp0); +PARSE_INIT (r3, "<exp2> = <plus> <exp>", eval_exp1); +PARSE_INIT (r4, "<exp2> = <minus> <exp>", eval_exp2); +PARSE_INIT (r5, "<exp2> = ", noop_match_rule); +PARSE_TYPE_INIT (exp, rule_match, 0, 0); +PARSE_TYPE_INIT (exp2, rule_match, 0, 0); + +PARSE_INIT (r6, "<term> = <factor><term2>", eval_term0); +PARSE_INIT (r7, "<term2> = <star> <term>", eval_term1); +PARSE_INIT (r8, "<term2> = <slash> <term>", eval_term2); +PARSE_INIT (r9, "<term2> = ", noop_match_rule); +PARSE_TYPE_INIT (term, rule_match, 0, 0); +PARSE_TYPE_INIT (term2, rule_match, 0, 0); + +PARSE_INIT (r11, "<factor> = <lpar> <exp> <rpar>", eval_factor1); +PARSE_INIT (r10, "<factor> = <number>", eval_factor0); +PARSE_INIT (r12, "<factor> = <minus> <factor>", eval_factor2); + +PARSE_TYPE_INIT (factor, rule_match, 0, 0); +#endif + +PARSE_INIT (r1, "eval <exp>", eval_result); + +#if 1 +PARSE_INIT (r2, "<exp> = <term><exp2>", eval_exp0); +PARSE_INIT (r3, "<exp2> = <plus> <exp>", eval_exp1); +PARSE_INIT (r4, "<exp2> = <minus> <exp>", eval_exp2); +PARSE_INIT (r5, "<exp2> = ", noop_match_rule); +PARSE_TYPE_INIT (exp, rule_match, 0, 0); +PARSE_TYPE_INIT (exp2, rule_match, 0, 0); + +PARSE_INIT (r6, "<term> = <factor><term2>", eval_term0); +PARSE_INIT (r7, "<term2> = <star> <term>", eval_term1); +PARSE_INIT (r8, "<term2> = <slash> <term>", eval_term2); +PARSE_INIT (r9, "<term2> = ", noop_match_rule); +PARSE_TYPE_INIT (term, rule_match, 0, 0); +PARSE_TYPE_INIT (term2, rule_match, 0, 0); + +PARSE_INIT (r11, "<factor> = <lpar> <exp> <rpar>", eval_factor1); +PARSE_INIT (r10, "<factor> = <number>", eval_factor0); +PARSE_INIT (r12, "<factor> = <minus> <factor>", eval_factor2); + +PARSE_TYPE_INIT (factor, rule_match, 0, 0); +#endif + +#if 0 +PARSE_TYPE_INIT (exp, rule_match, 0, 0); +PARSE_INIT (r6, "<exp> = a b", eval_term0); +PARSE_INIT (r7, "<exp> = c d", eval_term1); +PARSE_INIT (r9, "<exp> = ", noop_match_rule); +#endif + +#if 0 +#define foreach_rule_evaluator \ +_(0) \ +_(1) \ +_(2) \ +_(3) + +#define _(n) \ +vlib_parse_match_t eval##n (vlib_parse_main_t *pm, \ + vlib_parse_item_t *item, \ + vlib_parse_value_t *value) \ +{ \ + clib_warning ("%U", format_vlib_parse_value, pm); \ + return VLIB_PARSE_MATCH_DONE; \ +} +foreach_rule_evaluator +#undef _ +PARSE_INIT (r1, "eval <moo>", eval_result); + +PARSE_INIT (r2, "<moo> = cow", eval0); +PARSE_INIT (r4, "<moo> = ", eval1); +PARSE_TYPE_INIT (moo, rule_match, 0, 0); +#endif + + +clib_error_t * +test_init (vlib_main_t * vm) +{ + clib_error_t *error; + + if ((error = vlib_call_init_function (vm, parse_init))) + return error; + + return 0; +} + +VLIB_INIT_FUNCTION (test_init); + +clib_error_t * +vlib_stdlex_init (vlib_main_t * vm) +{ + vlib_lex_main_t *lm = &vlib_lex_main; + u16 top_index; + u16 slash_index, slash_star_index, slash_slash_index, slash_star_star_index; + u16 slash_token; + u16 word_index; + u16 zero_index, octal_index, decimal_index, hex_index, binary_index; + + top_index = vlib_lex_add_table ("top"); + +#define foreach_top_level_single_character_token \ + _('(', lpar) \ + _(')', rpar) \ + _(';', semi) \ + _('[', lbrack) \ + _(']', rbrack) \ + _('{', lcurly) \ + _('}', rcurly) \ + _('+', plus) \ + _('-', minus) \ + _('*', star) \ + _('%', percent) \ + _('@', atsign) \ + _(',', comma) \ + _('.', dot) \ + _('?', qmark) + +#define _(c,t) \ + vlib_lex_set_action_range(top_index,c,c,VLIB_LEX_RETURN,vlib_lex_add_token(lm, #t), top_index); + foreach_top_level_single_character_token; +#undef _ + + /* Numbers */ + zero_index = vlib_lex_add_table ("zero"); + octal_index = vlib_lex_add_table ("octal"); + decimal_index = vlib_lex_add_table ("decimal"); + hex_index = vlib_lex_add_table ("hex"); + binary_index = vlib_lex_add_table ("binary"); + + /* Support 0x 0b 0t and 0123 [octal] */ + vlib_lex_set_action_range (top_index, '0', '0', VLIB_LEX_START_NUMBER, 10, + zero_index); + vlib_lex_set_action_range (top_index, '1', '9', VLIB_LEX_START_NUMBER, 10, + decimal_index); + + vlib_lex_set_action_range (zero_index, 0, 0x7F, VLIB_LEX_RETURN_AND_RESCAN, + VLIB_LEX_number, top_index); + + vlib_lex_set_action_range (zero_index, 'x', 'x', VLIB_LEX_IGNORE, ~0, + hex_index); + vlib_lex_set_action_range (zero_index, 'b', 'b', VLIB_LEX_IGNORE, ~0, + binary_index); + vlib_lex_set_action_range (zero_index, 't', 't', VLIB_LEX_IGNORE, ~0, + decimal_index); + vlib_lex_set_action_range (zero_index, '0', '7', VLIB_LEX_START_NUMBER, 8, + octal_index); + + /* Octal */ + vlib_lex_set_action_range (octal_index, 0, 0x7f, VLIB_LEX_RETURN_AND_RESCAN, + VLIB_LEX_number, top_index); + vlib_lex_set_action_range (octal_index, '0', '7', VLIB_LEX_ADD_TO_NUMBER, 8, + octal_index); + + /* Decimal */ + vlib_lex_set_action_range (decimal_index, 0, 0x7f, + VLIB_LEX_RETURN_AND_RESCAN, VLIB_LEX_number, + top_index); + vlib_lex_set_action_range (decimal_index, '0', '9', VLIB_LEX_ADD_TO_NUMBER, + 10, decimal_index); + + /* Hex */ + vlib_lex_set_action_range (hex_index, 0, 0x7f, VLIB_LEX_RETURN_AND_RESCAN, + VLIB_LEX_number, top_index); + vlib_lex_set_action_range (hex_index, '0', '9', VLIB_LEX_ADD_TO_NUMBER, 16, + hex_index); + vlib_lex_set_action_range (hex_index, 'a', 'f', VLIB_LEX_ADD_TO_NUMBER, 16, + hex_index); + vlib_lex_set_action_range (hex_index, 'A', 'F', VLIB_LEX_ADD_TO_NUMBER, 16, + hex_index); + + /* Binary */ + vlib_lex_set_action_range (binary_index, 0, 0x7f, + VLIB_LEX_RETURN_AND_RESCAN, VLIB_LEX_number, + top_index); + vlib_lex_set_action_range (binary_index, '0', '1', VLIB_LEX_ADD_TO_NUMBER, + 2, binary_index); + + /* c/c++ comment syntax is the worst... */ + + slash_index = vlib_lex_add_table ("slash"); + slash_star_index = vlib_lex_add_table ("slash_star"); + slash_star_star_index = vlib_lex_add_table ("slash_star_star"); + slash_slash_index = vlib_lex_add_table ("slash_slash"); + slash_token = vlib_lex_add_token (lm, "slash"); + + /* Top level: see a slash, ignore, go to slash table */ + vlib_lex_set_action_range (top_index, '/', '/', VLIB_LEX_IGNORE, ~0, + slash_index); + + /* default for slash table: return SLASH, go to top table */ + vlib_lex_set_action_range (slash_index, 1, 0x7F, VLIB_LEX_RETURN_AND_RESCAN, + slash_token, top_index); + /* see slash-slash, go to s-s table */ + vlib_lex_set_action_range (slash_index, '/', '/', VLIB_LEX_IGNORE, ~0, + slash_slash_index); + /* see slash-star, go to s-* table */ + vlib_lex_set_action_range (slash_index, '*', '*', VLIB_LEX_IGNORE, ~0, + slash_star_index); + + /* EOL in s-s table, ignore, go to top table */ + vlib_lex_set_action_range (slash_slash_index, '\n', '\n', VLIB_LEX_IGNORE, + ~0, top_index); + + /* slash-star blah blah star */ + vlib_lex_set_action_range (slash_star_index, '*', '*', VLIB_LEX_IGNORE, ~0, + slash_star_star_index); + + /* slash star blah blah star slash */ + vlib_lex_set_action_range (slash_star_star_index, '/', '/', VLIB_LEX_IGNORE, + ~0, top_index); + + /* LT, =, GT */ + vlib_lex_set_action_range (top_index, '<', '<', VLIB_LEX_RETURN, + VLIB_LEX_lt, top_index); + vlib_lex_set_action_range (top_index, '=', '=', VLIB_LEX_RETURN, + VLIB_LEX_equals, top_index); + vlib_lex_set_action_range (top_index, '>', '>', VLIB_LEX_RETURN, + VLIB_LEX_gt, top_index); + + /* words, key and otherwise */ + word_index = vlib_lex_add_table ("word"); + + vlib_lex_set_action_range (top_index, 'a', 'z', VLIB_LEX_ADD_TO_TOKEN, ~0, + word_index); + vlib_lex_set_action_range (top_index, 'A', 'Z', VLIB_LEX_ADD_TO_TOKEN, ~0, + word_index); + + vlib_lex_set_action_range (word_index, 0, 0x7f, VLIB_LEX_KEYWORD_CHECK, ~0, + top_index); + + vlib_lex_set_action_range (word_index, 'a', 'z', VLIB_LEX_ADD_TO_TOKEN, ~0, + word_index); + vlib_lex_set_action_range (word_index, 'A', 'Z', VLIB_LEX_ADD_TO_TOKEN, ~0, + word_index); + vlib_lex_set_action_range (word_index, '_', '_', VLIB_LEX_ADD_TO_TOKEN, ~0, + word_index); + vlib_lex_set_action_range (word_index, '0', '9', VLIB_LEX_ADD_TO_TOKEN, ~0, + word_index); + + return 0; +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ |