diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/examples/vlib/elog_samples.c (renamed from src/vlib/elog_samples.c) | 0 | ||||
-rw-r--r-- | src/examples/vlib/plex_test.c | 527 | ||||
-rw-r--r-- | src/vlib/parse.c | 1007 | ||||
-rw-r--r-- | src/vlib/parse_builtin.c | 150 | ||||
-rw-r--r-- | src/vnet/ethernet/mac_swap.c | 397 | ||||
-rw-r--r-- | src/vnet/ip/ip4_test.c | 347 | ||||
-rw-r--r-- | src/vpp/app/sticky_hash.c | 581 | ||||
-rw-r--r-- | src/vppinfra/mod_test_hash.c | 27 | ||||
-rw-r--r-- | src/vppinfra/pfhash.c | 689 | ||||
-rw-r--r-- | src/vppinfra/test_pfhash.c | 322 | ||||
-rw-r--r-- | src/vppinfra/test_pool.c | 86 |
11 files changed, 0 insertions, 4133 deletions
diff --git a/src/vlib/elog_samples.c b/src/examples/vlib/elog_samples.c index a8c800df959..a8c800df959 100644 --- a/src/vlib/elog_samples.c +++ b/src/examples/vlib/elog_samples.c diff --git a/src/examples/vlib/plex_test.c b/src/examples/vlib/plex_test.c deleted file mode 100644 index ce0c8ef1141..00000000000 --- a/src/examples/vlib/plex_test.c +++ /dev/null @@ -1,527 +0,0 @@ -/* - * 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: - */ diff --git a/src/vlib/parse.c b/src/vlib/parse.c deleted file mode 100644 index 1c4500ce85a..00000000000 --- a/src/vlib/parse.c +++ /dev/null @@ -1,1007 +0,0 @@ -/* - * 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> - -#define PARSE_DEBUG 0 - -u16 word_type_index, number_type_index, eof_type_index, rule_eof_type_index, - plus_type_index, minus_type_index, star_type_index, slash_type_index, - lpar_type_index, rpar_type_index; - -u8 * -format_vlib_parse_value (u8 * s, va_list * args) -{ - vlib_parse_main_t *pm = va_arg (*args, vlib_parse_main_t *); - vlib_parse_type_t *type; - vlib_parse_value_t *v; - u16 type_index; - - s = format (s, "%d items:\n", vec_len (pm->parse_value)); - vec_foreach (v, pm->parse_value) - { - type_index = v->type; - type = pool_elt_at_index (pm->parse_types, type_index); - if (type->format_value) - s = format (s, "[%d]: %U\n", v - pm->parse_value, - type->format_value, v); - else - s = format (s, "[%d]: (nofun)\n", v - pm->parse_value); - } - return s; -} - -static u8 * -format_vlib_parse_match (u8 * s, va_list * args) -{ - vlib_parse_match_t m = va_arg (*args, vlib_parse_match_t); - char *t = 0; - switch (m) - { -#define _(a) case VLIB_PARSE_##a: t = #a; break; - foreach_parse_match_type -#undef _ - default: - t = 0; - break; - } - - if (t) - return format (s, "%s", t); - else - return format (s, "unknown 0x%x", m); -} - -static u8 * -format_vlib_parse_item (u8 * s, va_list * args) -{ - vlib_parse_main_t *pm = va_arg (*args, vlib_parse_main_t *); - vlib_parse_item_t *item = va_arg (*args, vlib_parse_item_t *); - vlib_parse_type_t *type = pool_elt_at_index (pm->parse_types, item->type); - - if (item->type == word_type_index) - s = format (s, "%s", item->value.as_pointer); - else - s = format (s, "<%s>", type->name); - return s; -} - -static u8 * -format_vlib_parse_graph (u8 * s, va_list * args) -{ - vlib_parse_main_t *pm = va_arg (*args, vlib_parse_main_t *); - vlib_parse_graph_t *node = va_arg (*args, vlib_parse_graph_t *); - vlib_parse_item_t *item; - vlib_parse_type_t *type; - - /* $$$ hash table */ - /* *INDENT-OFF* */ - pool_foreach (type, pm->parse_types, - ({ - if (type->rule_index == node - pm->parse_graph) - s = format (s, "\n<%s>\n", type->name); - })); -/* *INDENT-ON* */ - - if (pm->root_index == (node - pm->parse_graph)) - s = format (s, "\n<root>\n"); - - item = pool_elt_at_index (pm->parse_items, node->item); - - s = format (s, "[%d] %U ", node - pm->parse_graph, - format_vlib_parse_item, pm, item); - - if (node->peer == (u32) ~ 0) - s = format (s, "peer nil "); - else - s = format (s, "peer %4u ", node->peer); - - if (node->deeper == (u32) ~ 0) - s = format (s, "deeper nil "); - else - s = format (s, "deeper %4u ", node->deeper); - - return s; -} - -void -dump_parse_graph (void) -{ - vlib_parse_main_t *pm = &vlib_parse_main; - vlib_parse_graph_t *node; - - /* *INDENT-OFF* */ - pool_foreach (node, pm->parse_graph, ({ - fformat(stdout, "%U\n", format_vlib_parse_graph, pm, node); - })); -/* *INDENT-ON* */ -} - -always_inline void -parse_cleanup_value (vlib_parse_main_t * pm, vlib_parse_value_t * pv) -{ - vlib_parse_type_t *type = pool_elt_at_index (pm->parse_types, pv->type); - if (type->value_cleanup_function) - type->value_cleanup_function (pv); -} - -static void -parse_reset (vlib_parse_main_t * pm, u8 * input) -{ - vlib_lex_token_t *t; - vlib_parse_value_t *pv; - - vlib_lex_reset (pm->lex_main, input); - - vec_foreach (t, pm->tokens) vlib_lex_cleanup_token (t); - - vec_foreach (pv, pm->parse_value) parse_cleanup_value (pm, pv); - - _vec_len (pm->parse_value) = 0; - _vec_len (pm->tokens) = 0; - pm->current_token_index = 0; -} - -static void -parse_help (vlib_parse_main_t * pm, u32 index) -{ - vlib_parse_graph_t *node; - vlib_parse_item_t *item; - vlib_parse_type_t *type; - vlib_main_t *vm = pm->vlib_main; - u8 *help_input; - int i; - - help_input = vec_dup (pm->lex_main->input_vector); - - for (i = vec_len (help_input) - 1; i >= 0; i--) - if (help_input[i] == '?') - { - help_input[i] = 0; - _vec_len (help_input) = i; - break; - } - - for (i = vec_len (help_input) - 1; i >= 0; i--) - { - if (help_input[i] != ' ' && help_input[i] != '\t') - break; - help_input[i] = 0; - break; - } - _vec_len (help_input) = i + 1; - - while (index != (u32) ~ 0) - { - node = pool_elt_at_index (pm->parse_graph, index); - item = pool_elt_at_index (pm->parse_items, node->item); - type = pool_elt_at_index (pm->parse_types, item->type); - - if (item->type == eof_type_index && vec_len (pm->match_items) == 0) - /* do nothing */ ; - else if (item->type == word_type_index) - vlib_cli_output (vm, "%s %s\n", help_input, item->value.as_pointer); - else - vlib_cli_output (vm, "%s <%s>\n", help_input, type->name); - index = node->peer; - } - vec_free (help_input); -} - -static vlib_parse_match_t -parse_eval_internal (vlib_parse_main_t * pm, u32 index) -{ - vlib_parse_graph_t *node; - vlib_parse_item_t *item; - vlib_parse_type_t *type; - vlib_parse_value_t value, *pv; - vlib_parse_match_t rv; - u32 *partial_matches = 0; - vlib_lex_token_t *t; - u32 save_token_index = (u32) ~ 0, save_match_items = 0; - int had_value = 0; - - if (pm->current_token_index >= vec_len (pm->tokens)) - return VLIB_PARSE_MATCH_FAIL; - - /* current token */ - t = vec_elt_at_index (pm->tokens, pm->current_token_index); - - /* Help ? */ - if (PREDICT_FALSE (t->token == VLIB_LEX_qmark)) - { - parse_help (pm, index); - _vec_len (pm->match_items) = 0; - return VLIB_PARSE_MATCH_DONE; - } - - /* Across all peers at this level of the parse graph */ - while (index != (u32) ~ 0) - { - node = pool_elt_at_index (pm->parse_graph, index); - item = pool_elt_at_index (pm->parse_items, node->item); - type = pool_elt_at_index (pm->parse_types, item->type); - - /* - * Save the token index. We may have to back up several - * trie plies. Type-specific match functions can consume - * multiple tokens, and they may not be optimally careful - */ - save_token_index = pm->current_token_index; - save_match_items = vec_len (pm->match_items); - vec_add1 (pm->match_items, node->item); - - if (PARSE_DEBUG > 1) - clib_warning ("Try to match token %U against node %d", - format_vlib_lex_token, pm->lex_main, t, index); - - /* Call the type-specific match function */ - rv = type->match_function (pm, type, t, &value); - - if (PARSE_DEBUG > 1) - clib_warning ("returned %U", format_vlib_parse_match, rv); - - switch (rv) - { - case VLIB_PARSE_MATCH_VALUE: - /* - * Matched, and returned a value to append to the - * set of args passed to the action function - */ - value.type = item->type; - vec_add1 (pm->parse_value, value); - had_value = 1; - /* fallthrough */ - - case VLIB_PARSE_MATCH_FULL: - unambiguous_partial_match: - /* Consume the matched token */ - pm->current_token_index++; - - /* continue matching along this path */ - rv = parse_eval_internal (pm, node->deeper); - - /* this is not the right path */ - if (rv == VLIB_PARSE_MATCH_FAIL) - { - if (had_value) - { - /* Delete the value */ - value = pm->parse_value[vec_len (pm->parse_value) - 1]; - parse_cleanup_value (pm, &value); - _vec_len (pm->parse_value) -= 1; - } - /* Continue with the next sibling */ - pm->current_token_index = save_token_index; - _vec_len (pm->match_items) = save_match_items; - index = node->peer; - break; - } - return rv; - - case VLIB_PARSE_MATCH_PARTIAL: - /* Partial (substring) match, remember it but keep going */ - vec_add1 (partial_matches, node - pm->parse_graph); - index = node->peer; - break; - - case VLIB_PARSE_MATCH_FAIL: - /* Continue with the next sibling */ - index = node->peer; - _vec_len (pm->match_items) = save_match_items; - break; - - case VLIB_PARSE_MATCH_DONE: - /* Parse complete, invoke the action function */ - if (PARSE_DEBUG > 0) - clib_warning ("parse_value: %U", format_vlib_parse_value, pm); - - { - vlib_parse_eval_function_t *f = item->value.as_pointer; - if (f) - rv = f (pm, item, pm->parse_value); - } - - vec_foreach (pv, pm->parse_value) parse_cleanup_value (pm, pv); - _vec_len (pm->parse_value) = 0; - _vec_len (pm->match_items) = 0; - return rv; - - case VLIB_PARSE_MATCH_AMBIGUOUS: - case VLIB_PARSE_MATCH_EVAL_FAIL: - case VLIB_PARSE_MATCH_RULE: - _vec_len (pm->match_items) = save_match_items; - return rv; - } - } - - /* - * Out of siblings. If we have exactly one partial match - * we win - */ - if (vec_len (partial_matches) == 1) - { - index = partial_matches[0]; - node = pool_elt_at_index (pm->parse_graph, index); - vec_free (partial_matches); - goto unambiguous_partial_match; - } - - /* Ordinary loser */ - rv = VLIB_PARSE_MATCH_FAIL; - - /* Ambiguous loser */ - if (vec_len (partial_matches) > 1) - { - vec_free (partial_matches); - rv = VLIB_PARSE_MATCH_AMBIGUOUS; - } - - _vec_len (pm->match_items) = save_match_items; - return rv; -} - -vlib_parse_match_t -rule_match (vlib_parse_main_t * pm, vlib_parse_type_t * type, - vlib_lex_token_t * t, vlib_parse_value_t * valuep) -{ - vlib_parse_match_t rv; - static int recursion_level; - - if (PARSE_DEBUG > 1) - clib_warning ("[%d]: try to match type %s graph index %d", - recursion_level, type->name, type->rule_index); - recursion_level++; - rv = parse_eval_internal (pm, type->rule_index); - recursion_level--; - - /* Break the recusive unwind here... */ - if (rv == VLIB_PARSE_MATCH_RULE) - { - if (PARSE_DEBUG > 1) - clib_warning ("[%d]: type %s matched", recursion_level, type->name); - - return VLIB_PARSE_MATCH_FULL; - } - else - { - if (PARSE_DEBUG > 1) - clib_warning ("[%d]: type %s returns %U", recursion_level, type->name, - format_vlib_parse_match, rv); - } - return rv; -} - -static int -parse_eval (vlib_parse_main_t * pm, u8 * input) -{ - vlib_lex_token_t *t; - - parse_reset (pm, input); - - /* Tokenize the entire input vector */ - do - { - vec_add2 (pm->tokens, t, 1); - vlib_lex_get_token (pm->lex_main, t); - } - while (t->token != VLIB_LEX_eof); - - /* Feed it to the parser */ - return parse_eval_internal (pm, pm->root_index); -} - -/* Temporary vlib stub */ -vlib_parse_match_t -vlib_parse_eval (u8 * input) -{ - return parse_eval (&vlib_parse_main, input); -} - -u16 -parse_type_find_or_create (vlib_parse_main_t * pm, vlib_parse_type_t * t) -{ - uword *p; - vlib_parse_type_t *n; - u8 *name_copy; - - p = hash_get_mem (pm->parse_type_by_name_hash, t->name); - if (p) - return p[0]; - - pool_get (pm->parse_types, n); - *n = *t; - n->rule_index = (u32) ~ 0; - - name_copy = format (0, "%s%c", n->name, 0); - - hash_set_mem (pm->parse_type_by_name_hash, name_copy, n - pm->parse_types); - return n - pm->parse_types; -} - -u16 -parse_type_find_by_name (vlib_parse_main_t * pm, char *name) -{ - uword *p; - - p = hash_get_mem (pm->parse_type_by_name_hash, name); - if (p) - return p[0]; - - return (u16) ~ 0; -} - -u32 -parse_item_find_or_create (vlib_parse_main_t * pm, vlib_parse_item_t * item) -{ - uword *p; - vlib_parse_item_t *i; - - /* Exact match the entire item */ - p = mhash_get (&pm->parse_item_hash, item); - if (p) - return p[0]; - - pool_get (pm->parse_items, i); - *i = *item; - - mhash_set (&pm->parse_item_hash, i, i - pm->parse_items, 0); - return i - pm->parse_items; -} - -static void -parse_type_and_graph_init (vlib_parse_main_t * pm) -{ - u32 eof_index; - vlib_parse_type_t type; - vlib_parse_item_t item; - - memset (&type, 0, sizeof (type)); - -#define foreach_token_type \ - _ (eof) \ - _ (rule_eof) \ - _ (word) \ - _ (number) \ - _ (plus) \ - _ (minus) \ - _ (star) \ - _ (slash) \ - _ (lpar) \ - _ (rpar) - -#define _(a) a##_type_index = parse_type_find_by_name (pm, #a); - foreach_token_type -#undef _ - memset (&item, 0, sizeof (item)); - item.type = eof_type_index; - - eof_index = parse_item_find_or_create (pm, &item); - pm->root_index = (u32) ~ 0; - -#if 0 - pool_get (pm->parse_graph, g); - memset (g, 0xff, sizeof (*g)); - g->item = eof_index; - pm->root_index = 0; -#endif -} - - - -static void -tokenize (vlib_parse_main_t * pm, parse_registration_t * pr) -{ - vlib_lex_token_t *t; - pm->register_input = format (pm->register_input, - "%s%c", pr->initializer, 0); - - parse_reset (pm, pm->register_input); - - do - { - vec_add2 (pm->tokens, t, 1); - vlib_lex_get_token (pm->lex_main, t); - } - while (t->token != VLIB_LEX_eof); - _vec_len (pm->register_input) = 0; -} - -static int -is_typed_rule (vlib_parse_main_t * pm) -{ - vlib_lex_token_t *t = vec_elt_at_index (pm->tokens, 0); - - /* <mytype> = blah blah blah */ - if (vec_len (pm->tokens) >= 4 - && t[0].token == VLIB_LEX_lt - && t[1].token == VLIB_LEX_word - && t[2].token == VLIB_LEX_gt && t[3].token == VLIB_LEX_equals) - return 1; - return 0; -} - -static int -token_matches_graph_node (vlib_parse_main_t * pm, - vlib_lex_token_t * t, - vlib_parse_graph_t * node, - vlib_parse_item_t * item, - vlib_parse_type_t * type, u32 * token_increment) -{ - /* EOFs don't match */ - if (t->token == VLIB_LEX_eof) - return 0; - - /* New chain element is a word */ - if (t->token == VLIB_LEX_word) - { - /* but the item in hand is not a word */ - if (item->type != word_type_index) - return 0; - - /* Or it's not this particular word */ - if (strcmp (t->value.as_pointer, item->value.as_pointer)) - return 0; - *token_increment = 1; - return 1; - } - /* New chain element is a type-name: < TYPE-NAME > */ - if (t->token == VLIB_LEX_lt) - { - u16 token_type_index; - - /* < TYPE > */ - if (t[1].token != VLIB_LEX_word || t[2].token != VLIB_LEX_gt) - { - clib_warning (0, "broken type name in '%s'", pm->register_input); - return 0; - } - - token_type_index = parse_type_find_by_name (pm, t[1].value.as_pointer); - if (token_type_index == (u16) ~ 0) - { - clib_warning (0, "unknown type '%s'", t[1].value.as_pointer); - return 0; - } - - /* Its a known type but does not match. */ - if (item->type != token_type_index) - return 0; - - *token_increment = 3; - return 1; - } - clib_warning ("BUG: t->token = %d", t->token); - return 0; -} - -u32 -generate_subgraph_from_tokens (vlib_parse_main_t * pm, - vlib_lex_token_t * t, - u32 * new_subgraph_depth, - parse_registration_t * pr, int not_a_rule) -{ - vlib_parse_graph_t *g, *last_g; - vlib_parse_item_t new_item; - u32 rv = (u32) ~ 0, new_item_index, last_index = (u32) ~ 0; - u16 token_type_index; - u32 depth = 0; - - while (t < pm->tokens + vec_len (pm->tokens)) - { - memset (&new_item, 0, sizeof (new_item)); - - if (t->token == VLIB_LEX_word) - { - new_item.type = word_type_index; - new_item.value.as_pointer = vec_dup ((u8 *) t->value.as_pointer); - new_item_index = parse_item_find_or_create (pm, &new_item); - t++; - } - else if (t->token == VLIB_LEX_lt) - { - if (t[1].token != VLIB_LEX_word || t[2].token != VLIB_LEX_gt) - { - clib_warning ("broken type name in '%s'", pm->register_input); - goto screwed; - } - token_type_index = parse_type_find_by_name (pm, - t[1].value.as_pointer); - if (token_type_index == (u16) ~ 0) - { - clib_warning ("unknown type 2 '%s'", t[1].value.as_pointer); - goto screwed; - } - - new_item.type = token_type_index; - new_item.value.as_pointer = 0; - new_item_index = parse_item_find_or_create (pm, &new_item); - t += 3; /* skip < <type-name> and > */ - } - else if (t->token == VLIB_LEX_eof) - { - screwed: - new_item.type = not_a_rule ? eof_type_index : rule_eof_type_index; - new_item.value.as_pointer = pr->eof_match; - new_item_index = parse_item_find_or_create (pm, &new_item); - t++; - } - else - { - clib_warning ("unexpected token %U index %d in '%s'", - format_vlib_lex_token, pm->lex_main, t, - t - pm->tokens, pm->register_input); - goto screwed; - } - - pool_get (pm->parse_graph, g); - memset (g, 0xff, sizeof (*g)); - g->item = new_item_index; - depth++; - - if (rv == (u32) ~ 0) - { - rv = g - pm->parse_graph; - last_index = rv; - } - else - { - last_g = pool_elt_at_index (pm->parse_graph, last_index); - last_index = last_g->deeper = g - pm->parse_graph; - } - } - *new_subgraph_depth = depth; - return rv; -} - -static u32 -measure_depth (vlib_parse_main_t * pm, u32 index) -{ - vlib_parse_graph_t *node; - vlib_parse_item_t *item; - u32 max = 0; - u32 depth; - - if (index == (u32) ~ 0) - return 0; - - node = pool_elt_at_index (pm->parse_graph, index); - item = pool_elt_at_index (pm->parse_items, node->item); - - if (item->type == eof_type_index) - return 1; - - while (index != (u32) ~ 0) - { - node = pool_elt_at_index (pm->parse_graph, index); - depth = measure_depth (pm, node->deeper); - if (max < depth) - max = depth; - index = node->peer; - } - - return max + 1; -} - -static void -add_subgraph_to_graph (vlib_parse_main_t * pm, - u32 last_matching_index, - u32 graph_root_index, - u32 new_subgraph_index, u32 new_subgraph_depth) -{ - vlib_parse_graph_t *parent_node; - int new_subgraph_longest = 1; - u32 current_peer_index; - u32 current_depth; - vlib_parse_graph_t *current_peer = 0; - vlib_parse_graph_t *new_subgraph_node = - pool_elt_at_index (pm->parse_graph, new_subgraph_index); - - /* - * Case 1: top-level peer. Splice into the top-level - * peer chain according to rule depth - */ - if (last_matching_index == (u32) ~ 0) - { - u32 index = graph_root_index; - while (1) - { - current_peer = pool_elt_at_index (pm->parse_graph, index); - current_depth = measure_depth (pm, index); - if (current_depth < new_subgraph_depth - || current_peer->peer == (u32) ~ 0) - break; - index = current_peer->peer; - } - new_subgraph_node->peer = current_peer->peer; - current_peer->peer = new_subgraph_index; - return; - } - - parent_node = pool_elt_at_index (pm->parse_graph, last_matching_index); - current_peer_index = parent_node->deeper; - - while (current_peer_index != (u32) ~ 0) - { - current_peer = pool_elt_at_index (pm->parse_graph, current_peer_index); - current_depth = measure_depth (pm, current_peer_index); - if (current_depth < new_subgraph_depth) - break; - new_subgraph_longest = 0; - current_peer_index = current_peer->peer; - } - - ASSERT (current_peer); - - if (new_subgraph_longest) - { - new_subgraph_node->peer = parent_node->deeper; - parent_node->deeper = new_subgraph_index; - } - else - { - new_subgraph_node->peer = current_peer->peer; - current_peer->peer = new_subgraph_index; - } -} - -static clib_error_t * -parse_register_one (vlib_parse_main_t * pm, parse_registration_t * pr) -{ - u32 graph_root_index; - u16 subgraph_type_index = (u16) ~ 0; - vlib_parse_type_t *subgraph_type = 0; - vlib_lex_token_t *t; - vlib_parse_graph_t *node; - u32 node_index, last_index, token_increment, new_subgraph_index; - u32 new_subgraph_depth, last_matching_index; - vlib_parse_item_t *item; - vlib_parse_type_t *type; - - int use_main_graph = 1; - - tokenize (pm, pr); - - /* A typed rule? */ - if (is_typed_rule (pm)) - { - /* Get the type and its current subgraph root, if any */ - t = vec_elt_at_index (pm->tokens, 1); - subgraph_type_index = parse_type_find_by_name (pm, t->value.as_pointer); - if (subgraph_type_index == (u16) ~ 0) - return clib_error_return (0, "undeclared type '%s'", - t->value.as_pointer); - subgraph_type = - pool_elt_at_index (pm->parse_types, subgraph_type_index); - graph_root_index = subgraph_type->rule_index; - /* Skip "mytype> = */ - t += 3; - use_main_graph = 0; - } - else - { - /* top-level graph */ - graph_root_index = pm->root_index; - t = vec_elt_at_index (pm->tokens, 0); - } - - last_matching_index = (u32) ~ 0; - last_index = node_index = graph_root_index; - - /* Find the first token which isn't already being parsed */ - while (t < pm->tokens + vec_len (pm->tokens) && node_index != (u32) ~ 0) - { - node = pool_elt_at_index (pm->parse_graph, node_index); - item = pool_elt_at_index (pm->parse_items, node->item); - type = pool_elt_at_index (pm->parse_types, item->type); - last_index = node_index; - - if (token_matches_graph_node - (pm, t, node, item, type, &token_increment)) - { - t += token_increment; - last_matching_index = node_index; - node_index = node->deeper; - } - else - node_index = node->peer; - } - - new_subgraph_index = - generate_subgraph_from_tokens (pm, t, &new_subgraph_depth, pr, - use_main_graph); - - /* trivial cases: first graph node or first type rule */ - if (graph_root_index == (u32) ~ 0) - { - if (use_main_graph) - pm->root_index = new_subgraph_index; - else - subgraph_type->rule_index = new_subgraph_index; - return 0; - } - - add_subgraph_to_graph (pm, last_matching_index, graph_root_index, - new_subgraph_index, new_subgraph_depth); - return 0; -} - -static clib_error_t * -parse_register (vlib_main_t * vm, - parse_registration_t * lo, - parse_registration_t * hi, vlib_parse_main_t * pm) -{ - parse_registration_t *pr; - - for (pr = lo; pr < hi; pr = vlib_elf_section_data_next (pr, 0)) - vec_add1 (pm->parse_registrations, pr); - - return 0; -} - -static clib_error_t * -parse_register_one_type (vlib_parse_main_t * pm, vlib_parse_type_t * rp) -{ - (void) parse_type_find_or_create (pm, (vlib_parse_type_t *) rp); - return 0; -} - -static clib_error_t * -parse_type_register (vlib_main_t * vm, - vlib_parse_type_t * lo, - vlib_parse_type_t * hi, vlib_parse_main_t * pm) -{ - clib_error_t *error = 0; - vlib_parse_type_t *ptr; - - for (ptr = lo; ptr < hi; ptr = vlib_elf_section_data_next (ptr, 0)) - { - error = parse_register_one_type (pm, ptr); - if (error) - goto done; - } - -done: - return error; -} - -clib_error_t *vlib_stdlex_init (vlib_main_t * vm) __attribute__ ((weak)); -clib_error_t * -vlib_stdlex_init (vlib_main_t * vm) -{ - (void) vlib_lex_add_table ("ignore_everything"); - return 0; -} - -static int -compute_rule_length (parse_registration_t * r) -{ - int length, i; - vlib_parse_main_t *pm = &vlib_parse_main; - - if (r->rule_length) - return r->rule_length; - - length = 0; - - tokenize (pm, r); - length = vec_len (pm->tokens); - - /* Account for "<foo> = " in "<foo> = bar" etc. */ - if (is_typed_rule (pm)) - length -= 2; - - for (i = 0; i < vec_len (pm->tokens); i++) - { - switch (pm->tokens[i].token) - { - case VLIB_LEX_lt: - case VLIB_LEX_gt: - length -= 1; - - default: - break; - } - } - - ASSERT (length > 0); - r->rule_length = length; - return length; -} - -static int -rule_length_compare (parse_registration_t * r1, parse_registration_t * r2) -{ - compute_rule_length (r1); - compute_rule_length (r2); - /* Descending sort */ - return r2->rule_length - r1->rule_length; -} - - -static clib_error_t * -parse_init (vlib_main_t * vm) -{ - vlib_parse_main_t *pm = &vlib_parse_main; - vlib_lex_main_t *lm = &vlib_lex_main; - vlib_elf_section_bounds_t *b, *bounds; - clib_error_t *error = 0; - parse_registration_t *rule; - int i; - - if ((error = vlib_call_init_function (vm, lex_onetime_init))) - return error; - - if ((error = vlib_stdlex_init (vm))) - return error; - - if ((error = vlib_call_init_function (vm, parse_builtin_init))) - return error; - - pm->vlib_main = vm; - pm->lex_main = lm; - - mhash_init (&pm->parse_item_hash, sizeof (u32), sizeof (vlib_parse_item_t)); - pm->parse_type_by_name_hash = hash_create_string (0, sizeof (u32)); - - vec_validate (pm->parse_value, 16); - vec_validate (pm->tokens, 16); - vec_validate (pm->register_input, 32); - vec_validate (pm->match_items, 16); - - _vec_len (pm->parse_value) = 0; - _vec_len (pm->tokens) = 0; - _vec_len (pm->register_input) = 0; - _vec_len (pm->match_items) = 0; - - bounds = vlib_get_elf_section_bounds (vm, "parse_type_registrations"); - vec_foreach (b, bounds) - { - error = parse_type_register (vm, b->lo, b->hi, pm); - if (error) - break; - } - vec_free (bounds); - - parse_type_and_graph_init (pm); - - bounds = vlib_get_elf_section_bounds (vm, "parse_registrations"); - vec_foreach (b, bounds) - { - error = parse_register (vm, b->lo, b->hi, pm); - if (error) - break; - } - vec_free (bounds); - - vec_sort_with_function (pm->parse_registrations, rule_length_compare); - - for (i = 0; i < vec_len (pm->parse_registrations); i++) - { - rule = pm->parse_registrations[i]; - parse_register_one (pm, rule); - } - - return error; -} - -VLIB_INIT_FUNCTION (parse_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vlib/parse_builtin.c b/src/vlib/parse_builtin.c deleted file mode 100644 index 0ce716b539e..00000000000 --- a/src/vlib/parse_builtin.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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> - -always_inline void * -parse_last_match_value (vlib_parse_main_t * pm) -{ - vlib_parse_item_t *i; - i = pool_elt_at_index (pm->parse_items, - vec_elt (pm->match_items, - vec_len (pm->match_items) - 1)); - return i->value.as_pointer; -} - -vlib_parse_match_t -eof_match (vlib_parse_main_t * pm, vlib_parse_type_t * type, - vlib_lex_token_t * t, vlib_parse_value_t * valuep) -{ - return t->token == - VLIB_LEX_eof ? VLIB_PARSE_MATCH_DONE : VLIB_PARSE_MATCH_FAIL; -} - -PARSE_TYPE_INIT (eof, eof_match, 0 /* cleanup value */ , - 0 /* format value */ ); - -vlib_parse_match_t -rule_eof_match (vlib_parse_main_t * pm, vlib_parse_type_t * type, - vlib_lex_token_t * t, vlib_parse_value_t * valuep) -{ - vlib_parse_match_function_t *fp = parse_last_match_value (pm); - pm->current_token_index--; - return fp ? fp (pm, type, t, valuep) : VLIB_PARSE_MATCH_RULE; -} - -PARSE_TYPE_INIT (rule_eof, rule_eof_match, 0, 0); - -vlib_parse_match_t -word_match (vlib_parse_main_t * pm, vlib_parse_type_t * type, - vlib_lex_token_t * t, vlib_parse_value_t * valuep) -{ - u8 *tv, *iv; - int i; - - if (t->token != VLIB_LEX_word) - return VLIB_PARSE_MATCH_FAIL; - - tv = t->value.as_pointer; - iv = parse_last_match_value (pm); - - for (i = 0; tv[i]; i++) - { - if (tv[i] != iv[i]) - return VLIB_PARSE_MATCH_FAIL; - } - - return iv[i] == 0 ? VLIB_PARSE_MATCH_FULL : VLIB_PARSE_MATCH_PARTIAL; -} - -PARSE_TYPE_INIT (word, word_match, 0 /* clnup value */ , - 0 /* format value */ ); - -vlib_parse_match_t -number_match (vlib_parse_main_t * pm, vlib_parse_type_t * type, - vlib_lex_token_t * t, vlib_parse_value_t * valuep) -{ - if (t->token == VLIB_LEX_number) - { - valuep->value.as_uword = t->value.as_uword; - return VLIB_PARSE_MATCH_VALUE; - } - return VLIB_PARSE_MATCH_FAIL; -} - -static u8 * -format_value_number (u8 * s, va_list * args) -{ - vlib_parse_value_t *v = va_arg (*args, vlib_parse_value_t *); - uword a = v->value.as_uword; - - if (BITS (uword) == 64) - s = format (s, "%lld(0x%llx)", a, a); - else - s = format (s, "%ld(0x%lx)", a, a); - return s; -} - -PARSE_TYPE_INIT (number, number_match, 0 /* cln value */ , - format_value_number /* fmt value */ ); - - -#define foreach_vanilla_lex_match_function \ - _(plus) \ - _(minus) \ - _(star) \ - _(slash) \ - _(lpar) \ - _(rpar) - -#define LEX_MATCH_DEBUG 0 - -#define _(name) \ -vlib_parse_match_t name##_match (vlib_parse_main_t *pm, \ - vlib_parse_type_t *type, \ - vlib_lex_token_t *t, \ - vlib_parse_value_t *valuep) \ -{ \ - if (LEX_MATCH_DEBUG > 0) \ - clib_warning ("against %U returns %s", \ - format_vlib_lex_token, pm->lex_main, t, \ - (t->token == VLIB_LEX_##name) \ - ? "VLIB_PARSE_MATCH_FULL" : \ - "VLIB_PARSE_MATCH_FAIL"); \ - if (t->token == VLIB_LEX_##name) \ - return VLIB_PARSE_MATCH_FULL; \ - return VLIB_PARSE_MATCH_FAIL; \ -} \ - \ -PARSE_TYPE_INIT (name, name##_match, 0 /* cln value */, \ - 0 /* fmt val */); - -foreach_vanilla_lex_match_function -#undef _ -/* So we're linked in. */ -static clib_error_t * -parse_builtin_init (vlib_main_t * vm) -{ - return 0; -} - -VLIB_INIT_FUNCTION (parse_builtin_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/ethernet/mac_swap.c b/src/vnet/ethernet/mac_swap.c deleted file mode 100644 index c0fec12e61e..00000000000 --- a/src/vnet/ethernet/mac_swap.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * 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/vlib.h> -#include <vnet/pg/pg.h> -#include <vnet/ethernet/ethernet.h> -#include <vppinfra/error.h> -#include <vnet/devices/pci/ige.h> -#include <vnet/devices/pci/ixge.h> -#include <vnet/devices/pci/ixgev.h> - -typedef struct -{ - u32 cached_next_index; - u32 cached_sw_if_index; - - /* Hash table to map sw_if_index to next node index */ - uword *next_node_index_by_sw_if_index; - - /* convenience */ - vlib_main_t *vlib_main; - vnet_main_t *vnet_main; -} mac_swap_main_t; - -typedef struct -{ - u8 src[6]; - u8 dst[6]; - u32 sw_if_index; - u32 next_index; -} swap_trace_t; - -/* packet trace format function */ -static u8 * -format_swap_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - swap_trace_t *t = va_arg (*args, swap_trace_t *); - - s = format (s, "SWAP: dst now %U src now %U sw_if_index %d next_index %d", - format_ethernet_address, t->dst, - format_ethernet_address, t->src, t->sw_if_index, t->next_index); - return s; -} - -#define foreach_hw_driver_next \ - _(IP4) \ - _(IP6) \ - _(ETHERNET) - -mac_swap_main_t mac_swap_main; - -static vlib_node_registration_t mac_swap_node; - -#define foreach_mac_swap_error \ -_(SWAPS, "mac addresses swapped") - -typedef enum -{ -#define _(sym,str) MAC_SWAP_ERROR_##sym, - foreach_mac_swap_error -#undef _ - MAC_SWAP_N_ERROR, -} mac_swap_error_t; - -static char *mac_swap_error_strings[] = { -#define _(sym,string) string, - foreach_mac_swap_error -#undef _ -}; - -/* - * To drop a pkt and increment one of the previous counters: - * - * set b0->error = error_node->errors[RANDOM_ERROR_SAMPLE]; - * set next0 to a disposition index bound to "error-drop". - * - * To manually increment the specific counter MAC_SWAP_ERROR_SAMPLE: - * - * vlib_node_t *n = vlib_get_node (vm, mac_swap.index); - * u32 node_counter_base_index = n->error_heap_index; - * vlib_error_main_t * em = &vm->error_main; - * em->counters[node_counter_base_index + MAC_SWAP_ERROR_SAMPLE] += 1; - * - */ - -typedef enum -{ - MAC_SWAP_NEXT_DROP, - MAC_SWAP_N_NEXT, -} mac_swap_next_t; - -static uword -mac_swap_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, vlib_frame_t * frame) -{ - u32 n_left_from, *from, *to_next; - mac_swap_next_t next_index; - mac_swap_main_t *msm = &mac_swap_main; - vlib_node_t *n = vlib_get_node (vm, mac_swap_node.index); - u32 node_counter_base_index = n->error_heap_index; - vlib_error_main_t *em = &vm->error_main; - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - - while (n_left_from > 0) - { - u32 n_left_to_next; - - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from >= 4 && n_left_to_next >= 2) - { - u32 bi0, bi1; - vlib_buffer_t *b0, *b1; - u32 next0, next1; - u32 sw_if_index0, sw_if_index1; - uword *p0, *p1; - u64 tmp0a, tmp0b; - u64 tmp1a, tmp1b; - ethernet_header_t *h0, *h1; - - - /* Prefetch next iteration. */ - { - vlib_buffer_t *p2, *p3; - - p2 = vlib_get_buffer (vm, from[2]); - p3 = vlib_get_buffer (vm, from[3]); - - vlib_prefetch_buffer_header (p2, LOAD); - vlib_prefetch_buffer_header (p3, LOAD); - - CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE); - CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE); - } - - to_next[0] = bi0 = from[0]; - to_next[1] = bi1 = from[1]; - from += 2; - to_next += 2; - n_left_from -= 2; - n_left_to_next -= 2; - - b0 = vlib_get_buffer (vm, bi0); - b1 = vlib_get_buffer (vm, bi1); - - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - next0 = msm->cached_next_index; - sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX]; - next1 = msm->cached_next_index; - - if (PREDICT_FALSE (msm->cached_sw_if_index != sw_if_index0)) - { - p0 = - hash_get (msm->next_node_index_by_sw_if_index, sw_if_index0); - if (p0 == 0) - { - vnet_hw_interface_t *hw0; - - hw0 = vnet_get_sup_hw_interface (msm->vnet_main, - sw_if_index0); - - next0 = vlib_node_add_next (msm->vlib_main, - mac_swap_node.index, - hw0->output_node_index); - hash_set (msm->next_node_index_by_sw_if_index, - sw_if_index0, next0); - } - else - next0 = p0[0]; - msm->cached_sw_if_index = sw_if_index0; - msm->cached_next_index = next0; - next1 = next0; - } - if (PREDICT_FALSE (msm->cached_sw_if_index != sw_if_index1)) - { - p1 = - hash_get (msm->next_node_index_by_sw_if_index, sw_if_index1); - if (p1 == 0) - { - vnet_hw_interface_t *hw1; - - hw1 = vnet_get_sup_hw_interface (msm->vnet_main, - sw_if_index1); - - next1 = vlib_node_add_next (msm->vlib_main, - mac_swap_node.index, - hw1->output_node_index); - hash_set (msm->next_node_index_by_sw_if_index, - sw_if_index1, next1); - } - else - next1 = p1[0]; - msm->cached_sw_if_index = sw_if_index1; - msm->cached_next_index = next1; - } - - em->counters[node_counter_base_index + MAC_SWAP_ERROR_SWAPS] += 2; - - /* reset buffer so we always point at the MAC hdr */ - vlib_buffer_reset (b0); - vlib_buffer_reset (b1); - h0 = vlib_buffer_get_current (b0); - h1 = vlib_buffer_get_current (b1); - - /* Swap 2 x src and dst mac addresses using 8-byte load/stores */ - tmp0a = clib_net_to_host_u64 (((u64 *) (h0->dst_address))[0]); - tmp1a = clib_net_to_host_u64 (((u64 *) (h1->dst_address))[0]); - tmp0b = clib_net_to_host_u64 (((u64 *) (h0->src_address))[0]); - tmp1b = clib_net_to_host_u64 (((u64 *) (h1->src_address))[0]); - ((u64 *) (h0->dst_address))[0] = clib_host_to_net_u64 (tmp0b); - ((u64 *) (h1->dst_address))[0] = clib_host_to_net_u64 (tmp1b); - /* Move the ethertype from "b" to "a" */ - tmp0a &= ~(0xFFFF); - tmp1a &= ~(0xFFFF); - tmp0a |= tmp0b & 0xFFFF; - ((u64 *) (h0->src_address))[0] = clib_host_to_net_u64 (tmp0a); - tmp1a |= tmp1b & 0xFFFF; - ((u64 *) (h1->src_address))[0] = clib_host_to_net_u64 (tmp1a); - - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE))) - { - if (b0->flags & VLIB_BUFFER_IS_TRACED) - { - swap_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - clib_memcpy (t->src, h0->src_address, 6); - clib_memcpy (t->dst, h0->dst_address, 6); - t->sw_if_index = sw_if_index0; - t->next_index = next0; - } - if (b1->flags & VLIB_BUFFER_IS_TRACED) - { - swap_trace_t *t = - vlib_add_trace (vm, node, b1, sizeof (*t)); - clib_memcpy (t->src, h1->src_address, 6); - clib_memcpy (t->dst, h1->dst_address, 6); - t->sw_if_index = sw_if_index1; - t->next_index = next1; - } - } - - vlib_validate_buffer_enqueue_x2 (vm, node, next_index, - to_next, n_left_to_next, - bi0, bi1, next0, next1); - } - - while (n_left_from > 0 && n_left_to_next > 0) - { - u32 bi0; - vlib_buffer_t *b0; - u32 next0; - u32 sw_if_index0; - uword *p0; - u64 tmp0a, tmp0b; - ethernet_header_t *h0; - - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - next0 = msm->cached_next_index; - - if (PREDICT_FALSE (msm->cached_sw_if_index != sw_if_index0)) - { - p0 = - hash_get (msm->next_node_index_by_sw_if_index, sw_if_index0); - if (p0 == 0) - { - vnet_hw_interface_t *hw0; - - hw0 = vnet_get_sup_hw_interface (msm->vnet_main, - sw_if_index0); - - next0 = vlib_node_add_next (msm->vlib_main, - mac_swap_node.index, - hw0->output_node_index); - hash_set (msm->next_node_index_by_sw_if_index, - sw_if_index0, next0); - } - else - next0 = p0[0]; - msm->cached_sw_if_index = sw_if_index0; - msm->cached_next_index = next0; - } - - em->counters[node_counter_base_index + MAC_SWAP_ERROR_SWAPS] += 1; - - /* reset buffer so we always point at the MAC hdr */ - vlib_buffer_reset (b0); - h0 = vlib_buffer_get_current (b0); - - /* Exchange src and dst, preserve the ethertype */ - tmp0a = clib_net_to_host_u64 (((u64 *) (h0->dst_address))[0]); - tmp0b = clib_net_to_host_u64 (((u64 *) (h0->src_address))[0]); - ((u64 *) (h0->dst_address))[0] = clib_host_to_net_u64 (tmp0b); - tmp0a &= ~(0xFFFF); - tmp0a |= tmp0b & 0xFFFF; - ((u64 *) (h0->src_address))[0] = clib_host_to_net_u64 (tmp0a); - - /* ship it */ - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) - && (b0->flags & VLIB_BUFFER_IS_TRACED))) - { - swap_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t)); - clib_memcpy (t->src, h0->src_address, 6); - clib_memcpy (t->dst, h0->dst_address, 6); - t->sw_if_index = sw_if_index0; - t->next_index = next0; - } - - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - bi0, next0); - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - return frame->n_vectors; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (mac_swap_node,static) = { - .function = mac_swap_node_fn, - .name = "mac-swap", - .vector_size = sizeof (u32), - .format_trace = format_swap_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(mac_swap_error_strings), - .error_strings = mac_swap_error_strings, - - .n_next_nodes = MAC_SWAP_N_NEXT, - - /* edit / add dispositions here */ - .next_nodes = { - [MAC_SWAP_NEXT_DROP] = "error-drop", - }, -}; -/* *INDENT-ON* */ - -clib_error_t * -mac_swap_init (vlib_main_t * vm) -{ - mac_swap_main_t *msm = &mac_swap_main; - - msm->next_node_index_by_sw_if_index = hash_create (0, sizeof (uword)); - msm->cached_next_index = (u32) ~ 0; - msm->cached_sw_if_index = (u32) ~ 0; - msm->vlib_main = vm; - msm->vnet_main = vnet_get_main (); - - /* Driver RX nodes send pkts here... */ -#define _(a) ixge_set_next_node (IXGE_RX_NEXT_##a##_INPUT, "mac-swap"); - foreach_hw_driver_next -#undef _ -#define _(a) ixgev_set_next_node (IXGEV_RX_NEXT_##a##_INPUT, "mac-swap"); - foreach_hw_driver_next -#undef _ -#define _(a) ige_set_next_node (IGE_RX_NEXT_##a##_INPUT, "mac-swap"); - foreach_hw_driver_next -#undef _ - return 0; -} - -VLIB_INIT_FUNCTION (mac_swap_init); - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/ip/ip4_test.c b/src/vnet/ip/ip4_test.c deleted file mode 100644 index 73dabfdc23a..00000000000 --- a/src/vnet/ip/ip4_test.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * 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 <vnet/ip/ip.h> -#include <vnet/ethernet/ethernet.h> - -/** - * @file - * @brief IPv4 FIB Tester. - * - * Not compiled in by default. IPv4 FIB tester. Add, probe, delete a bunch of - * random routes / masks and make sure that the mtrie agrees with - * the hash-table FIB. - * - * Manipulate the FIB by means of the debug CLI commands, to minimize - * the chances of doing something idiotic. - */ - -/* - * These routines need to be redeclared non-static elsewhere. - * - * Also: rename ip_route() -> vnet_ip_route_cmd() and add the usual - * test_route_init() call to main.c - */ -clib_error_t *vnet_ip_route_cmd (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd_arg); - -int ip4_lookup_validate (ip4_address_t * a, u32 fib_index0); - -ip4_fib_t *find_fib_by_table_index_or_id (ip4_main_t * im, - u32 table_index_or_id, u32 flags); - -/* Routes to insert/delete/probe in FIB */ -typedef struct -{ - ip4_address_t address; - u32 mask_width; - u32 interface_id; /* not an xx_if_index */ -} test_route_t; - -typedef struct -{ - /* Test routes in use */ - test_route_t *route_pool; - - /* Number of fake ethernets created */ - u32 test_interfaces_created; -} test_main_t; - -test_main_t test_main; - -/* fake ethernet device class, distinct from "fake-ethX" */ -static u8 * -format_test_interface_name (u8 * s, va_list * args) -{ - u32 dev_instance = va_arg (*args, u32); - return format (s, "test-eth%d", dev_instance); -} - -static uword -dummy_interface_tx (vlib_main_t * vm, - vlib_node_runtime_t * node, vlib_frame_t * frame) -{ - clib_warning ("you shouldn't be here, leaking buffers..."); - return frame->n_vectors; -} - -/* *INDENT-OFF* */ -VNET_DEVICE_CLASS (test_interface_device_class,static) = { - .name = "Test interface", - .format_device_name = format_test_interface_name, - .tx_function = dummy_interface_tx, -}; -/* *INDENT-ON* */ - -static clib_error_t * -thrash (vlib_main_t * vm, - unformat_input_t * main_input, vlib_cli_command_t * cmd_arg) -{ - u32 seed = 0xdeaddabe; - u32 niter = 10; - u32 nroutes = 10; - u32 ninterfaces = 4; - f64 min_mask_bits = 7.0; - f64 max_mask_bits = 32.0; - u32 table_id = 11; /* my amp goes to 11 (use fib 11) */ - u32 table_index; - int iter, i; - u8 *cmd; - test_route_t *tr; - test_main_t *tm = &test_main; - ip4_main_t *im = &ip4_main; - vnet_main_t *vnm = vnet_get_main (); - unformat_input_t cmd_input; - f64 rf; - u32 *masks = 0; - u32 tmp; - u32 hw_if_index; - clib_error_t *error = 0; - uword *p; - unformat_input_t _line_input, *line_input = &_line_input; - u8 hw_address[6]; - ip4_fib_t *fib; - int verbose = 0; - - /* Precompute mask width -> mask vector */ - tmp = (u32) ~ 0; - vec_validate (masks, 32); - for (i = 32; i > 0; i--) - { - masks[i] = tmp; - tmp <<= 1; - } - - if (unformat_user (main_input, unformat_line_input, line_input)) - { - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "seed %d", &seed)) - ; - else if (unformat (line_input, "niter %d", &niter)) - ; - else if (unformat (line_input, "nroutes %d", &nroutes)) - ; - else if (unformat (line_input, "ninterfaces %d", &ninterfaces)) - ; - else if (unformat (line_input, "min-mask-bits %d", &tmp)) - min_mask_bits = (f64) tmp; - else if (unformat (line_input, "max-mask-bits %d", &tmp)) - max_mask_bits = (f64) tmp; - else if (unformat (line_input, "verbose")) - verbose = 1; - else - { - error = clib_error_return (0, "unknown input `%U'", - format_unformat_error, line_input); - goto done; - } - } - } - - /* Find or create FIB table 11 */ - fib = ip4_fib_find_or_create_fib_by_table_id (table_id); - - for (i = tm->test_interfaces_created; i < ninterfaces; i++) - { - vnet_hw_interface_t *hw; - memset (hw_address, 0, sizeof (hw_address)); - hw_address[0] = 0xd0; - hw_address[1] = 0x0f; - hw_address[5] = i; - - error = ethernet_register_interface - (vnm, test_interface_device_class.index, i /* instance */ , - hw_address, &hw_if_index, - /* flag change */ 0); - - /* Fake interfaces use FIB table 11 */ - hw = vnet_get_hw_interface (vnm, hw_if_index); - vec_validate (im->fib_index_by_sw_if_index, hw->sw_if_index); - im->fib_index_by_sw_if_index[hw->sw_if_index] = fib->index; - ip4_sw_interface_enable_disable (sw_if_index, 1); - } - - tm->test_interfaces_created = ninterfaces; - - /* Find fib index corresponding to FIB id 11 */ - p = hash_get (im->fib_index_by_table_id, table_id); - if (p == 0) - { - vlib_cli_output (vm, "Couldn't map fib id %d to fib index\n", table_id); - goto done; - } - table_index = p[0]; - - for (iter = 0; iter < niter; iter++) - { - /* Pick random routes to install */ - for (i = 0; i < nroutes; i++) - { - int j; - - pool_get (tm->route_pool, tr); - memset (tr, 0, sizeof (*tr)); - - again: - rf = random_f64 (&seed); - tr->mask_width = (u32) (min_mask_bits - + rf * (max_mask_bits - min_mask_bits)); - tmp = random_u32 (&seed); - tmp &= masks[tr->mask_width]; - tr->address.as_u32 = clib_host_to_net_u32 (tmp); - - /* We can't add the same address/mask twice... */ - for (j = 0; j < i; j++) - { - test_route_t *prev; - prev = pool_elt_at_index (tm->route_pool, j); - if ((prev->address.as_u32 == tr->address.as_u32) - && (prev->mask_width == tr->mask_width)) - goto again; - } - - rf = random_f64 (&seed); - tr->interface_id = (u32) (rf * ninterfaces); - } - - /* Add them */ - for (i = 0; i < nroutes; i++) - { - tr = pool_elt_at_index (tm->route_pool, i); - cmd = format (0, "add table %d %U/%d via test-eth%d", - table_id, - format_ip4_address, &tr->address, - tr->mask_width, tr->interface_id); - vec_add1 (cmd, 0); - if (verbose) - fformat (stderr, "ip route %s\n", cmd); - unformat_init_string (&cmd_input, (char *) cmd, vec_len (cmd) - 1); - error = vnet_ip_route_cmd (vm, &cmd_input, cmd_arg); - if (error) - clib_error_report (error); - unformat_free (&cmd_input); - vec_free (cmd); - } - /* Probe them */ - for (i = 0; i < nroutes; i++) - { - tr = pool_elt_at_index (tm->route_pool, i); - if (!ip4_lookup_validate (&tr->address, table_index)) - { - if (verbose) - fformat (stderr, "test lookup table %d %U\n", - table_index, format_ip4_address, &tr->address); - - fformat (stderr, "FAIL-after-insert: %U/%d\n", - format_ip4_address, &tr->address, tr->mask_width); - } - } - - /* Delete them */ - for (i = 0; i < nroutes; i++) - { - int j; - tr = pool_elt_at_index (tm->route_pool, i); - if (0) - cmd = format (0, "del table %d %U/%d via test-eth%d", - table_id, - format_ip4_address, &tr->address, - tr->mask_width, tr->interface_id); - else - cmd = format (0, "del table %d %U/%d", - table_id, - format_ip4_address, &tr->address, tr->mask_width); - vec_add1 (cmd, 0); - if (verbose) - fformat (stderr, "ip route %s\n", cmd); - unformat_init_string (&cmd_input, (char *) cmd, vec_len (cmd) - 1); - error = vnet_ip_route_cmd (vm, &cmd_input, cmd_arg); - if (error) - clib_error_report (error); - unformat_free (&cmd_input); - vec_free (cmd); - - /* Make sure all undeleted routes still work */ - for (j = i + 1; j < nroutes; j++) - { - test_route_t *rr; /* remaining route */ - rr = pool_elt_at_index (tm->route_pool, j); - if (!ip4_lookup_validate (&rr->address, table_index)) - { - if (verbose) - fformat (stderr, "test lookup table %d %U\n", - table_index, format_ip4_address, &rr->address); - - fformat (stderr, "FAIL: %U/%d AWOL\n", - format_ip4_address, &rr->address, rr->mask_width); - fformat (stderr, " iter %d after %d of %d deletes\n", - iter, i, nroutes); - fformat (stderr, " last route deleted %U/%d\n", - format_ip4_address, &tr->address, tr->mask_width); - } - } - } - - pool_free (tm->route_pool); - } - -done: - unformat_free (line_input); - - return error; -} - -/*? - * This command in not in the build by default. It is an internal - * command used to test the route functonality. - * - * Create test routes on IPv4 FIB table 11. Table will be created if it - * does not exist. - * - * There are several optional attributes: - * - If not provided, <seed> defaults to 0xdeaddabe. - * - If not provided, <num-iter> defaults to 10. - * - If not provided, <num-iface> defaults to 4. - * - If not provided, <min-mask> defaults to 7.0. - * - If not provided, <max-mask> defaults to 32.0. - * - * @cliexpar - * Example of how to run: - * @cliexcmd{test route} -?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (test_route_command, static) = { - .path = "test route", - .short_help = "test route [seed <seed-num>] [niter <num-iter>] [ninterfaces <num-iface>] [min-mask-bits <min-mask>] [max-mask-bits <max-mask>] [verbose]", .function = thrash, - .function = thrash, -}; -/* *INDENT-ON* */ - -clib_error_t * -test_route_init (vlib_main_t * vm) -{ - return 0; -} - -VLIB_INIT_FUNCTION (test_route_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vpp/app/sticky_hash.c b/src/vpp/app/sticky_hash.c deleted file mode 100644 index 5569c6770e6..00000000000 --- a/src/vpp/app/sticky_hash.c +++ /dev/null @@ -1,581 +0,0 @@ -/* - * 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 <vnet/l2/l2_classify.h> - -#include <vlib/vlib.h> -#include <vnet/vnet.h> -#include <vnet/pg/pg.h> -#include <vnet/ip/ip.h> -#include <vnet/ip/ip_packet.h> -#include <vnet/ip/ip4_packet.h> -#include <vnet/ip/ip6_packet.h> -#include <vppinfra/error.h> - -typedef struct -{ - u32 fwd_entry_index; - u32 rev_entry_index; - /* Not strictly needed, for show command */ - u32 fib_index; -} sticky_hash_session_t; - -typedef struct -{ - u32 cached_next_index; - - /* next index added to l2_classify */ - u32 fwd_miss_next_index; - - /* session pool */ - sticky_hash_session_t *sessions; - - /* Forward and reverse data session setup buffers */ - u8 fdata[3 * sizeof (u32x4)]; - u8 rdata[3 * sizeof (u32x4)]; - - /* convenience variables */ - vlib_main_t *vlib_main; - vnet_main_t *vnet_main; - vnet_classify_main_t *vnet_classify_main; - l2_input_classify_main_t *l2_input_classify_main; -} -sticky_hash_main_t; - -typedef struct -{ - /* $$$$ fill in with per-pkt trace data */ - u32 next_index; - u32 sw_if_index; -} sticky_hash_miss_trace_t; - -/* packet trace format function */ -static u8 * -format_sticky_hash_miss_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - sticky_hash_miss_trace_t *t = va_arg (*args, sticky_hash_miss_trace_t *); - - s = format (s, "STICKY_HASH_MISS: sw_if_index %d", t->sw_if_index); - return s; -} - -typedef CLIB_PACKED (struct - { - ethernet_header_t eh; ip4_header_t ip; - }) classify_data_or_mask_t; - -sticky_hash_main_t sticky_hash_main; - -vlib_node_registration_t sticky_hash_miss_node; - -#define foreach_sticky_hash_miss_error \ -_(MISSES, "forward flow classify misses") - -typedef enum -{ -#define _(sym,str) STICKY_HASH_MISS_ERROR_##sym, - foreach_sticky_hash_miss_error -#undef _ - STICKY_HASH_MISS_N_ERROR, -} sticky_hash_miss_error_t; - -static char *sticky_hash_miss_error_strings[] = { -#define _(sym,string) string, - foreach_sticky_hash_miss_error -#undef _ -}; - -/* - * To drop a pkt and increment one of the previous counters: - * - * set b0->error = error_node->errors[STICKY_HASH_MISS_ERROR_EXAMPLE]; - * set next0 to a disposition index bound to "error-drop". - * - * To manually increment the specific counter STICKY_HASH_MISS_ERROR_EXAMPLE: - * - * vlib_node_t *n = vlib_get_node (vm, sticky_hash_miss.index); - * u32 node_counter_base_index = n->error_heap_index; - * vlib_error_main_t * em = &vm->error_main; - * em->counters[node_counter_base_index + STICKY_HASH_MISS_ERROR_EXAMPLE] += 1; - * - */ - -typedef enum -{ - STICKY_HASH_MISS_NEXT_IP4_INPUT, - STICKY_HASH_MISS_N_NEXT, -} sticky_hash_miss_next_t; - -static uword -sticky_hash_miss_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, vlib_frame_t * frame) -{ - u32 n_left_from, *from, *to_next; - sticky_hash_miss_next_t next_index; - sticky_hash_main_t *mp = &sticky_hash_main; - vlib_node_t *n = vlib_get_node (vm, sticky_hash_miss_node.index); - u32 node_counter_base_index = n->error_heap_index; - vlib_error_main_t *em = &vm->error_main; - vnet_classify_main_t *cm = mp->vnet_classify_main; - ip4_main_t *im = &ip4_main; - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - - while (n_left_from > 0) - { - u32 n_left_to_next; - - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - u32 bi0; - vlib_buffer_t *b0; - u32 next0; - u32 sw_if_index0; - u32 fib_index0, ft_index0, rt_index0; - vnet_classify_table_3_t *ft0, *rt0; - vnet_classify_entry_3_t *fe0, *re0; - classify_data_or_mask_t *h0; - u8 was_found0; - ip4_fib_t *fib0; - sticky_hash_session_t *s; - u32 tmp; - - /* speculatively enqueue b0 to the current next frame */ - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - next0 = mp->cached_next_index; - - h0 = vlib_buffer_get_current (b0); - - /* Add forward and reverse entries for this flow */ - clib_memcpy (mp->fdata, h0, sizeof (mp->fdata)); - clib_memcpy (mp->rdata, h0, sizeof (mp->rdata)); - - h0 = (classify_data_or_mask_t *) (mp->rdata); - - /* swap src + dst addresses to form reverse data */ - tmp = h0->ip.src_address.as_u32; - h0->ip.src_address.as_u32 = h0->ip.dst_address.as_u32; - h0->ip.dst_address.as_u32 = tmp; - - /* dig up fwd + rev tables */ - fib_index0 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index0); - fib0 = vec_elt_at_index (im->fibs, fib_index0); - - ft_index0 = fib0->fwd_classify_table_index; - rt_index0 = fib0->rev_classify_table_index; - - ft0 = (vnet_classify_table_3_t *) - pool_elt_at_index (cm->tables, ft_index0); - rt0 = (vnet_classify_table_3_t *) - pool_elt_at_index (cm->tables, rt_index0); - - fe0 = - vnet_classify_find_or_add_entry_3 (ft0, mp->fdata, &was_found0); - fe0->next_index = L2_INPUT_CLASSIFY_NEXT_IP4_INPUT; - fe0->advance = sizeof (ethernet_header_t); - - re0 = vnet_classify_find_or_add_entry_3 (rt0, mp->rdata, 0); - re0->next_index = L2_INPUT_CLASSIFY_NEXT_IP4_INPUT; /* $$$ FIXME */ - re0->advance = sizeof (ethernet_header_t); - - /* Note: we could get a whole vector of misses for the same sess */ - if (was_found0 == 0) - { - pool_get (mp->sessions, s); - - fe0->opaque_index = s - mp->sessions; - re0->opaque_index = s - mp->sessions; - - s->fwd_entry_index = fe0 - ft0->entries; - s->rev_entry_index = re0 - rt0->entries; - s->fib_index = fib_index0; - } - - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) - && (b0->flags & VLIB_BUFFER_IS_TRACED))) - { - sticky_hash_miss_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->sw_if_index = sw_if_index0; - t->next_index = next0; - } - - em->counters[node_counter_base_index + - STICKY_HASH_MISS_ERROR_MISSES] += 1; - - vlib_buffer_advance (b0, sizeof (ethernet_header_t)); - - /* verify speculative enqueue, maybe switch current next frame */ - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - bi0, next0); - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - return frame->n_vectors; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (sticky_hash_miss_node) = { - .function = sticky_hash_miss_node_fn, - .name = "sticky-hash-miss", - .vector_size = sizeof (u32), - .format_trace = format_sticky_hash_miss_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(sticky_hash_miss_error_strings), - .error_strings = sticky_hash_miss_error_strings, - - .n_next_nodes = STICKY_HASH_MISS_N_NEXT, - - /* edit / add dispositions here */ - .next_nodes = { - [STICKY_HASH_MISS_NEXT_IP4_INPUT] = "ip4-input", - }, -}; -/* *INDENT-ON* */ - -clib_error_t * -sticky_hash_miss_init (vlib_main_t * vm) -{ - sticky_hash_main_t *mp = &sticky_hash_main; - - mp->vlib_main = vm; - mp->vnet_main = vnet_get_main (); - mp->vnet_classify_main = &vnet_classify_main; - mp->l2_input_classify_main = &l2_input_classify_main; - - return 0; -} - -VLIB_INIT_FUNCTION (sticky_hash_miss_init); - -static int ip4_sticky_hash_enable_disable - (sticky_hash_main_t * mp, - u32 fwd_sw_if_index, u8 * fwd_mask, - u32 rev_sw_if_index, u8 * rev_mask, u32 nbuckets, int enable_disable) -{ - ip4_main_t *im = &ip4_main; - u32 fib_index; - ip4_fib_t *fib; - vnet_classify_main_t *cm = mp->vnet_classify_main; - l2_input_classify_main_t *l2cm = mp->l2_input_classify_main; - vnet_classify_table_3_t *ft, *rt; - - fib_index = vec_elt (im->fib_index_by_sw_if_index, fwd_sw_if_index); - fib = vec_elt_at_index (im->fibs, fib_index); - - if (fib->fwd_classify_table_index == ~0) - { - /* Set up forward table */ - ft = (vnet_classify_table_3_t *) - vnet_classify_new_table (cm, fwd_mask, nbuckets, - 0 /* skip */ , 3 /* match */ ); - fib->fwd_classify_table_index - = ft - (vnet_classify_table_3_t *) cm->tables; - mp->fwd_miss_next_index = - vlib_node_add_next (mp->vlib_main, l2_input_classify_node.index, - sticky_hash_miss_node.index); - ft->miss_next_index = mp->fwd_miss_next_index; - - /* Set up reverse table */ - rt = (vnet_classify_table_3_t *) - vnet_classify_new_table (cm, rev_mask, nbuckets, - 0 /* skip */ , 3 /* match */ ); - fib->rev_classify_table_index - = rt - (vnet_classify_table_3_t *) cm->tables; - } - - vec_validate - (l2cm->classify_table_index_by_sw_if_index[L2_INPUT_CLASSIFY_TABLE_IP4], - fwd_sw_if_index); - - vec_validate - (l2cm->classify_table_index_by_sw_if_index[L2_INPUT_CLASSIFY_TABLE_IP6], - fwd_sw_if_index); - - vec_validate - (l2cm->classify_table_index_by_sw_if_index[L2_INPUT_CLASSIFY_TABLE_OTHER], - fwd_sw_if_index); - - l2cm->classify_table_index_by_sw_if_index[L2_INPUT_CLASSIFY_TABLE_IP4] - [fwd_sw_if_index] = fib->fwd_classify_table_index; - - l2cm->classify_table_index_by_sw_if_index[L2_INPUT_CLASSIFY_TABLE_IP6] - [fwd_sw_if_index] = ~0; - - l2cm->classify_table_index_by_sw_if_index[L2_INPUT_CLASSIFY_TABLE_OTHER] - [fwd_sw_if_index] = ~0; - - - vec_validate - (l2cm->classify_table_index_by_sw_if_index[L2_INPUT_CLASSIFY_TABLE_IP4], - rev_sw_if_index); - - vec_validate - (l2cm->classify_table_index_by_sw_if_index[L2_INPUT_CLASSIFY_TABLE_IP6], - rev_sw_if_index); - - vec_validate - (l2cm->classify_table_index_by_sw_if_index[L2_INPUT_CLASSIFY_TABLE_OTHER], - rev_sw_if_index); - - - l2cm->classify_table_index_by_sw_if_index[L2_INPUT_CLASSIFY_TABLE_IP4] - [rev_sw_if_index] = fib->rev_classify_table_index; - - l2cm->classify_table_index_by_sw_if_index[L2_INPUT_CLASSIFY_TABLE_IP6] - [rev_sw_if_index] = ~0; - - l2cm->classify_table_index_by_sw_if_index[L2_INPUT_CLASSIFY_TABLE_OTHER] - [rev_sw_if_index] = ~0; - - vnet_l2_input_classify_enable_disable (fwd_sw_if_index, enable_disable); - vnet_l2_input_classify_enable_disable (rev_sw_if_index, enable_disable); - return 0; -} - -static clib_error_t * -ip4_sticky_hash_init_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - u32 fwd_sw_if_index = ~0, rev_sw_if_index = ~0; - int enable_disable = 1; - u32 nbuckets = 2; - int rv; - sticky_hash_main_t *mp = &sticky_hash_main; - classify_data_or_mask_t fwd_mask, rev_mask; - u8 *fm = 0, *rm = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat - (input, "fwd %U", unformat_vnet_sw_interface, mp->vnet_main, - &fwd_sw_if_index)) - ; - if (unformat - (input, "rev %U", unformat_vnet_sw_interface, mp->vnet_main, - &rev_sw_if_index)) - ; - else if (unformat (input, "nbuckets %d", &nbuckets)) - ; - else if (unformat (input, "disable")) - enable_disable = 0; - - else - break; - } - - nbuckets = 1 << max_log2 (nbuckets); - - if (fwd_sw_if_index == ~0) - return clib_error_return (0, "fwd interface not set"); - - if (rev_sw_if_index == ~0) - return clib_error_return (0, "rev interface not set"); - - if (!is_pow2 (nbuckets)) - return clib_error_return (0, "nbuckets %d not a power of 2", nbuckets); - - ASSERT (sizeof (fwd_mask) <= 3 * sizeof (u32x4)); - - /* Mask on src/dst address, depending on direction */ - memset (&fwd_mask, 0, sizeof (fwd_mask)); - memset (&fwd_mask.ip.src_address, 0xff, 4); - - memset (&rev_mask, 0, sizeof (rev_mask)); - memset (&rev_mask.ip.dst_address, 0xff, 4); - - vec_validate (fm, 3 * sizeof (u32x4) - 1); - vec_validate (rm, 3 * sizeof (u32x4) - 1); - - clib_memcpy (fm, &fwd_mask, sizeof (fwd_mask)); - clib_memcpy (rm, &rev_mask, sizeof (rev_mask)); - - rv = ip4_sticky_hash_enable_disable (mp, fwd_sw_if_index, fm, - rev_sw_if_index, rm, - nbuckets, enable_disable); - - vec_free (fm); - vec_free (rm); - switch (rv) - { - case 0: - return 0; - - default: - return clib_error_return (0, - "ip4_sticky_hash_enable_disable returned %d", - rv); - } - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (sticky_hash_init_command, static) = { - .path = "ip sticky classify", - .short_help = "ip sticky classify fwd <intfc> rev <intfc> " - "[nbuckets <nn>][disable]", - .function = ip4_sticky_hash_init_command_fn, -}; -/* *INDENT-ON* */ - - -u8 * -format_sticky_hash_session (u8 * s, va_list * args) -{ - sticky_hash_main_t *mp = va_arg (*args, sticky_hash_main_t *); - sticky_hash_session_t *session = va_arg (*args, sticky_hash_session_t *); - vnet_classify_table_3_t *t; - vnet_classify_entry_3_t *e; - ip4_main_t *im = &ip4_main; - vnet_classify_main_t *cm = mp->vnet_classify_main; - ip4_fib_t *fib; - classify_data_or_mask_t *match; - - fib = vec_elt_at_index (im->fibs, session->fib_index); - - t = (vnet_classify_table_3_t *) - pool_elt_at_index (cm->tables, fib->fwd_classify_table_index); - e = pool_elt_at_index (t->entries, session->fwd_entry_index); - match = (classify_data_or_mask_t *) (e->key); - - s = format - (s, - "[%6d] fwd src %U next index %d session %d fib %d\n" - " hits %lld last-heard %.6f\n", - e - t->entries, - format_ip4_address, &match->ip.src_address, - e->next_index, e->opaque_index, fib->table_id, e->hits, e->last_heard); - - if (e->opaque_index != session - mp->sessions) - s = format (s, "WARNING: forward session index mismatch!\n"); - - t = (vnet_classify_table_3_t *) - pool_elt_at_index (cm->tables, fib->rev_classify_table_index); - e = pool_elt_at_index (t->entries, session->rev_entry_index); - match = (classify_data_or_mask_t *) (e->key); - - s = format - (s, - "[%6d] rev dst %U next index %d session %d\n" - " hits %lld last-heard %.6f\n", - e - t->entries, - format_ip4_address, &match->ip.dst_address, - e->next_index, e->opaque_index, e->hits, e->last_heard); - - if (e->opaque_index != session - mp->sessions) - s = format (s, "WARNING: reverse session index mismatch!\n"); - s = format (s, "---------\n"); - - return s; -} - -static clib_error_t * -show_ip4_sticky_hash_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - sticky_hash_main_t *mp = &sticky_hash_main; - sticky_hash_session_t *s; - int verbose = 0; - int dump_classifier_tables = 0; - ip4_fib_t *fib; - ip4_main_t *im4 = &ip4_main; - vnet_classify_main_t *cm = mp->vnet_classify_main; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "verbose")) - verbose = 1; - else if (unformat (input, "dump-tables") - || unformat (input, "dump-classifier-tables")) - dump_classifier_tables = 1; - else - break; - } - - if (pool_elts (mp->sessions) == 0) - vlib_cli_output (vm, "No ip sticky hash sessions"); - - - vlib_cli_output (vm, "%d active sessions\n", pool_elts (mp->sessions)); - - vec_foreach (fib, im4->fibs) - { - if (fib->fwd_classify_table_index != ~0) - vlib_cli_output (vm, "fib %d fwd table: \n%U", - fib->table_id, - format_classify_table, - cm, - pool_elt_at_index - (cm->tables, fib->fwd_classify_table_index), - dump_classifier_tables); - if (fib->rev_classify_table_index != ~0) - vlib_cli_output (vm, "fib %d rev table: \n%U", - fib->table_id, - format_classify_table, - cm, - pool_elt_at_index - (cm->tables, fib->rev_classify_table_index), - dump_classifier_tables); - } - - if (verbose) - { - /* *INDENT-OFF* */ - pool_foreach (s, mp->sessions, - ({ - vlib_cli_output (vm, "%U", format_sticky_hash_session, mp, s); - })); - /* *INDENT-ON* */ - } - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (show_sticky_hash_command, static) = { - .path = "show sticky classify", - .short_help = "Display sticky classifier tables", - .function = show_ip4_sticky_hash_command_fn, -}; -/* *INDENT-ON* */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vppinfra/mod_test_hash.c b/src/vppinfra/mod_test_hash.c deleted file mode 100644 index b3fa676d2e2..00000000000 --- a/src/vppinfra/mod_test_hash.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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 <vppinfra/linux_kernel_init.h> -#include <vppinfra/hash.h> - -CLIB_LINUX_KERNEL_MODULE ("test_hash", test_hash_main, - /* kernel-thread flags */ 0 & CLONE_KERNEL); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vppinfra/pfhash.c b/src/vppinfra/pfhash.c deleted file mode 100644 index 3b9fa8f34aa..00000000000 --- a/src/vppinfra/pfhash.c +++ /dev/null @@ -1,689 +0,0 @@ -/* - Copyright (c) 2013 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 <vppinfra/pfhash.h> -#include <vppinfra/format.h> - -/* This is incredibly handy when debugging */ -u32 vl (void *v) __attribute__ ((weak)); -u32 -vl (void *v) -{ - return vec_len (v); -} - -#if defined(CLIB_HAVE_VEC128) && ! defined (__ALTIVEC__) - -typedef struct -{ - u8 *key[16]; - u64 value; -} pfhash_show_t; - -static int -sh_compare (pfhash_show_t * sh0, pfhash_show_t * sh1) -{ - return ((i32) (sh0->value) - ((i32) sh1->value)); -} - -u8 * -format_pfhash (u8 * s, va_list * args) -{ - pfhash_t *p = va_arg (*args, pfhash_t *); - int verbose = va_arg (*args, int); - - if (p == 0 || p->overflow_hash == 0 || p->buckets == 0) - { - s = format (s, "*** uninitialized ***"); - return s; - } - - s = format (s, "Prefetch hash '%s'\n", p->name); - s = - format (s, " %d buckets, %u bucket overflows, %.1f%% bucket overflow \n", - vec_len (p->buckets), p->overflow_count, - 100.0 * ((f64) p->overflow_count) / ((f64) vec_len (p->buckets))); - if (p->nitems) - s = - format (s, - " %u items, %u items in overflow, %.1f%% items in overflow\n", - p->nitems, p->nitems_in_overflow, - 100.0 * ((f64) p->nitems_in_overflow) / ((f64) p->nitems)); - - if (verbose) - { - pfhash_show_t *shs = 0, *sh; - hash_pair_t *hp; - int i, j; - - for (i = 0; i < vec_len (p->buckets); i++) - { - pfhash_kv_t *kv; - pfhash_kv_16_t *kv16; - pfhash_kv_8_t *kv8; - pfhash_kv_8v8_t *kv8v8; - pfhash_kv_4_t *kv4; - - if (p->buckets[i] == 0 || p->buckets[i] == PFHASH_BUCKET_OVERFLOW) - continue; - - kv = pool_elt_at_index (p->kvp, p->buckets[i]); - - switch (p->key_size) - { - case 16: - kv16 = &kv->kv16; - for (j = 0; j < 3; j++) - { - if (kv16->values[j] != (u32) ~ 0) - { - vec_add2 (shs, sh, 1); - clib_memcpy (sh->key, &kv16->kb.k_u32x4[j], - p->key_size); - sh->value = kv16->values[j]; - } - } - break; - case 8: - if (p->value_size == 4) - { - kv8 = &kv->kv8; - for (j = 0; j < 5; j++) - { - if (kv8->values[j] != (u32) ~ 0) - { - vec_add2 (shs, sh, 1); - clib_memcpy (sh->key, &kv8->kb.k_u64[j], - p->key_size); - sh->value = kv8->values[j]; - } - } - } - else - { - kv8v8 = &kv->kv8v8; - for (j = 0; j < 4; j++) - { - if (kv8v8->values[j] != (u64) ~ 0) - { - vec_add2 (shs, sh, 1); - clib_memcpy (sh->key, &kv8v8->kb.k_u64[j], - p->key_size); - sh->value = kv8v8->values[j]; - } - } - - } - break; - case 4: - kv4 = &kv->kv4; - for (j = 0; j < 8; j++) - { - if (kv4->values[j] != (u32) ~ 0) - { - vec_add2 (shs, sh, 1); - clib_memcpy (sh->key, &kv4->kb.kb[j], p->key_size); - sh->value = kv4->values[j]; - } - } - break; - } - } - - /* *INDENT-OFF* */ - hash_foreach_pair (hp, p->overflow_hash, - ({ - vec_add2 (shs, sh, 1); - clib_memcpy (sh->key, (u8 *)hp->key, p->key_size); - sh->value = hp->value[0]; - })); - /* *INDENT-ON* */ - - vec_sort_with_function (shs, sh_compare); - - for (i = 0; i < vec_len (shs); i++) - { - sh = vec_elt_at_index (shs, i); - s = format (s, " %U value %u\n", format_hex_bytes, sh->key, - p->key_size, sh->value); - } - vec_free (shs); - } - return s; -} - - -void abort (void); - -void -pfhash_init (pfhash_t * p, char *name, u32 key_size, u32 value_size, - u32 nbuckets) -{ - pfhash_kv_t *kv; - memset (p, 0, sizeof (*p)); - u32 key_bytes; - - switch (key_size) - { - case 4: - key_bytes = 4; - break; - case 8: - key_bytes = 8; - break; - case 16: - key_bytes = 16; - break; - default: - ASSERT (0); - abort (); - } - - switch (value_size) - { - case 4: - case 8: - break; - default: - ASSERT (0); - abort (); - } - - - p->name = format (0, "%s", name); - vec_add1 (p->name, 0); - p->overflow_hash = hash_create_mem (0, key_bytes, sizeof (uword)); - - nbuckets = 1 << (max_log2 (nbuckets)); - - /* This sets the entire bucket array to zero */ - vec_validate (p->buckets, nbuckets - 1); - p->key_size = key_size; - p->value_size = value_size; - - /* - * Unset buckets implicitly point at the 0th pool elt. - * All search routines will return ~0 if they go there. - */ - pool_get_aligned (p->kvp, kv, 16); - memset (kv, 0xff, sizeof (*kv)); -} - -static pfhash_kv_16_t * -pfhash_get_kv_16 (pfhash_t * p, u32 bucket_contents, - u32x4 * key, u32 * match_index) -{ - u32x4 diff[3]; - u32 is_equal[3]; - pfhash_kv_16_t *kv = 0; - - *match_index = (u32) ~ 0; - - kv = &p->kvp[bucket_contents].kv16; - - diff[0] = u32x4_sub (kv->kb.k_u32x4[0], key[0]); - diff[1] = u32x4_sub (kv->kb.k_u32x4[1], key[0]); - diff[2] = u32x4_sub (kv->kb.k_u32x4[2], key[0]); - - is_equal[0] = u32x4_zero_byte_mask (diff[0]) == 0xffff; - is_equal[1] = u32x4_zero_byte_mask (diff[1]) == 0xffff; - is_equal[2] = u32x4_zero_byte_mask (diff[2]) == 0xffff; - - if (is_equal[0]) - *match_index = 0; - if (is_equal[1]) - *match_index = 1; - if (is_equal[2]) - *match_index = 2; - - return kv; -} - -static pfhash_kv_8_t * -pfhash_get_kv_8 (pfhash_t * p, u32 bucket_contents, - u64 * key, u32 * match_index) -{ - pfhash_kv_8_t *kv; - - *match_index = (u32) ~ 0; - - kv = &p->kvp[bucket_contents].kv8; - - if (kv->kb.k_u64[0] == key[0]) - *match_index = 0; - if (kv->kb.k_u64[1] == key[0]) - *match_index = 1; - if (kv->kb.k_u64[2] == key[0]) - *match_index = 2; - if (kv->kb.k_u64[3] == key[0]) - *match_index = 3; - if (kv->kb.k_u64[4] == key[0]) - *match_index = 4; - - return kv; -} - -static pfhash_kv_8v8_t * -pfhash_get_kv_8v8 (pfhash_t * p, - u32 bucket_contents, u64 * key, u32 * match_index) -{ - pfhash_kv_8v8_t *kv; - - *match_index = (u32) ~ 0; - - kv = &p->kvp[bucket_contents].kv8v8; - - if (kv->kb.k_u64[0] == key[0]) - *match_index = 0; - if (kv->kb.k_u64[1] == key[0]) - *match_index = 1; - if (kv->kb.k_u64[2] == key[0]) - *match_index = 2; - if (kv->kb.k_u64[3] == key[0]) - *match_index = 3; - - return kv; -} - -static pfhash_kv_4_t * -pfhash_get_kv_4 (pfhash_t * p, u32 bucket_contents, - u32 * key, u32 * match_index) -{ - u32x4 vector_key; - u32x4 is_equal[2]; - u32 zbm[2], winner_index; - pfhash_kv_4_t *kv; - - *match_index = (u32) ~ 0; - - kv = &p->kvp[bucket_contents].kv4; - - vector_key = u32x4_splat (key[0]); - - is_equal[0] = u32x4_is_equal (kv->kb.k_u32x4[0], vector_key); - is_equal[1] = u32x4_is_equal (kv->kb.k_u32x4[1], vector_key); - zbm[0] = ~u32x4_zero_byte_mask (is_equal[0]) & 0xFFFF; - zbm[1] = ~u32x4_zero_byte_mask (is_equal[1]) & 0xFFFF; - - if (PREDICT_FALSE ((zbm[0] == 0) && (zbm[1] == 0))) - return kv; - - winner_index = min_log2 (zbm[0]) >> 2; - winner_index = zbm[1] ? (4 + (min_log2 (zbm[1]) >> 2)) : winner_index; - - *match_index = winner_index; - return kv; -} - -static pfhash_kv_t * -pfhash_get_internal (pfhash_t * p, u32 bucket_contents, - void *key, u32 * match_index) -{ - pfhash_kv_t *kv = 0; - - switch (p->key_size) - { - case 16: - kv = - (pfhash_kv_t *) pfhash_get_kv_16 (p, bucket_contents, key, - match_index); - break; - case 8: - if (p->value_size == 4) - kv = (pfhash_kv_t *) pfhash_get_kv_8 (p, bucket_contents, - key, match_index); - else - kv = (pfhash_kv_t *) pfhash_get_kv_8v8 (p, bucket_contents, - key, match_index); - break; - case 4: - kv = - (pfhash_kv_t *) pfhash_get_kv_4 (p, bucket_contents, key, - match_index); - break; - default: - ASSERT (0); - } - return kv; -} - -u64 -pfhash_get (pfhash_t * p, u32 bucket, void *key) -{ - pfhash_kv_t *kv; - u32 match_index = ~0; - pfhash_kv_16_t *kv16; - pfhash_kv_8_t *kv8; - pfhash_kv_8v8_t *kv8v8; - pfhash_kv_4_t *kv4; - - u32 bucket_contents = pfhash_read_bucket_prefetch_kv (p, bucket); - - if (bucket_contents == PFHASH_BUCKET_OVERFLOW) - { - uword *hp; - - hp = hash_get_mem (p->overflow_hash, key); - if (hp) - return hp[0]; - return (u64) ~ 0; - } - - kv = pfhash_get_internal (p, bucket_contents, key, &match_index); - if (match_index == (u32) ~ 0) - return (u64) ~ 0; - - kv16 = (void *) kv; - kv8 = (void *) kv; - kv4 = (void *) kv; - kv8v8 = (void *) kv; - - switch (p->key_size) - { - case 16: - return (kv16->values[match_index] == (u32) ~ 0) - ? (u64) ~ 0 : (u64) kv16->values[match_index]; - case 8: - if (p->value_size == 4) - return (kv8->values[match_index] == (u32) ~ 0) - ? (u64) ~ 0 : (u64) kv8->values[match_index]; - else - return kv8v8->values[match_index]; - case 4: - return (kv4->values[match_index] == (u32) ~ 0) - ? (u64) ~ 0 : (u64) kv4->values[match_index]; - default: - ASSERT (0); - } - return (u64) ~ 0; -} - -void -pfhash_set (pfhash_t * p, u32 bucket, void *key, void *value) -{ - u32 bucket_contents = pfhash_read_bucket_prefetch_kv (p, bucket); - u32 match_index = (u32) ~ 0; - pfhash_kv_t *kv; - pfhash_kv_16_t *kv16; - pfhash_kv_8_t *kv8; - pfhash_kv_8v8_t *kv8v8; - pfhash_kv_4_t *kv4; - int i; - u8 *kcopy; - - if (bucket_contents == PFHASH_BUCKET_OVERFLOW) - { - hash_pair_t *hp; - hp = hash_get_pair_mem (p->overflow_hash, key); - if (hp) - { - clib_warning ("replace value 0x%08x with value 0x%08x", - hp->value[0], (u64) value); - hp->value[0] = (u64) value; - return; - } - kcopy = clib_mem_alloc (p->key_size); - clib_memcpy (kcopy, key, p->key_size); - hash_set_mem (p->overflow_hash, kcopy, value); - p->nitems++; - p->nitems_in_overflow++; - return; - } - - if (bucket_contents == 0) - { - pool_get_aligned (p->kvp, kv, 16); - memset (kv, 0xff, sizeof (*kv)); - p->buckets[bucket] = kv - p->kvp; - } - else - kv = pfhash_get_internal (p, bucket_contents, key, &match_index); - - kv16 = (void *) kv; - kv8 = (void *) kv; - kv8v8 = (void *) kv; - kv4 = (void *) kv; - - p->nitems++; - - if (match_index != (u32) ~ 0) - { - switch (p->key_size) - { - case 16: - kv16->values[match_index] = (u32) (u64) value; - return; - - case 8: - if (p->value_size == 4) - kv8->values[match_index] = (u32) (u64) value; - else - kv8v8->values[match_index] = (u64) value; - return; - - case 4: - kv4->values[match_index] = (u64) value; - return; - - default: - ASSERT (0); - } - } - - switch (p->key_size) - { - case 16: - for (i = 0; i < 3; i++) - { - if (kv16->values[i] == (u32) ~ 0) - { - clib_memcpy (&kv16->kb.k_u32x4[i], key, p->key_size); - kv16->values[i] = (u32) (u64) value; - return; - } - } - /* copy bucket contents to overflow hash tbl */ - for (i = 0; i < 3; i++) - { - kcopy = clib_mem_alloc (p->key_size); - clib_memcpy (kcopy, &kv16->kb.k_u32x4[i], p->key_size); - hash_set_mem (p->overflow_hash, kcopy, kv16->values[i]); - p->nitems_in_overflow++; - } - /* Add new key to overflow */ - kcopy = clib_mem_alloc (p->key_size); - clib_memcpy (kcopy, key, p->key_size); - hash_set_mem (p->overflow_hash, kcopy, value); - p->buckets[bucket] = PFHASH_BUCKET_OVERFLOW; - p->overflow_count++; - p->nitems_in_overflow++; - return; - - case 8: - if (p->value_size == 4) - { - for (i = 0; i < 5; i++) - { - if (kv8->values[i] == (u32) ~ 0) - { - clib_memcpy (&kv8->kb.k_u64[i], key, 8); - kv8->values[i] = (u32) (u64) value; - return; - } - } - /* copy bucket contents to overflow hash tbl */ - for (i = 0; i < 5; i++) - { - kcopy = clib_mem_alloc (p->key_size); - clib_memcpy (kcopy, &kv8->kb.k_u64[i], 8); - hash_set_mem (p->overflow_hash, kcopy, kv8->values[i]); - p->nitems_in_overflow++; - } - } - else - { - for (i = 0; i < 4; i++) - { - if (kv8v8->values[i] == (u64) ~ 0) - { - clib_memcpy (&kv8v8->kb.k_u64[i], key, 8); - kv8v8->values[i] = (u64) value; - return; - } - } - /* copy bucket contents to overflow hash tbl */ - for (i = 0; i < 4; i++) - { - kcopy = clib_mem_alloc (p->key_size); - clib_memcpy (kcopy, &kv8v8->kb.k_u64[i], 8); - hash_set_mem (p->overflow_hash, kcopy, kv8v8->values[i]); - p->nitems_in_overflow++; - } - - } - /* Add new key to overflow */ - kcopy = clib_mem_alloc (p->key_size); - clib_memcpy (kcopy, key, p->key_size); - hash_set_mem (p->overflow_hash, kcopy, value); - p->buckets[bucket] = PFHASH_BUCKET_OVERFLOW; - p->overflow_count++; - p->nitems_in_overflow++; - return; - - case 4: - for (i = 0; i < 8; i++) - { - if (kv4->values[i] == (u32) ~ 0) - { - clib_memcpy (&kv4->kb.kb[i], key, 4); - kv4->values[i] = (u32) (u64) value; - return; - } - } - /* copy bucket contents to overflow hash tbl */ - for (i = 0; i < 8; i++) - { - kcopy = clib_mem_alloc (p->key_size); - clib_memcpy (kcopy, &kv4->kb.kb[i], 4); - hash_set_mem (p->overflow_hash, kcopy, kv4->values[i]); - p->nitems_in_overflow++; - } - /* Add new key to overflow */ - kcopy = clib_mem_alloc (p->key_size); - clib_memcpy (kcopy, key, p->key_size); - hash_set_mem (p->overflow_hash, kcopy, value); - p->buckets[bucket] = PFHASH_BUCKET_OVERFLOW; - p->overflow_count++; - p->nitems_in_overflow++; - return; - - default: - ASSERT (0); - } -} - -void -pfhash_unset (pfhash_t * p, u32 bucket, void *key) -{ - u32 bucket_contents = pfhash_read_bucket_prefetch_kv (p, bucket); - u32 match_index = (u32) ~ 0; - pfhash_kv_t *kv; - pfhash_kv_16_t *kv16; - pfhash_kv_8_t *kv8; - pfhash_kv_8v8_t *kv8v8; - pfhash_kv_4_t *kv4; - void *oldkey; - - if (bucket_contents == PFHASH_BUCKET_OVERFLOW) - { - hash_pair_t *hp; - hp = hash_get_pair_mem (p->overflow_hash, key); - if (hp) - { - oldkey = (void *) hp->key; - hash_unset_mem (p->overflow_hash, key); - clib_mem_free (oldkey); - p->nitems--; - p->nitems_in_overflow--; - } - return; - } - - kv = pfhash_get_internal (p, bucket_contents, key, &match_index); - if (match_index == (u32) ~ 0) - return; - - p->nitems--; - - kv16 = (void *) kv; - kv8 = (void *) kv; - kv8v8 = (void *) kv; - kv4 = (void *) kv; - - switch (p->key_size) - { - case 16: - kv16->values[match_index] = (u32) ~ 0; - return; - - case 8: - if (p->value_size == 4) - kv8->values[match_index] = (u32) ~ 0; - else - kv8v8->values[match_index] = (u64) ~ 0; - return; - - case 4: - kv4->values[match_index] = (u32) ~ 0; - return; - - default: - ASSERT (0); - } -} - -void -pfhash_free (pfhash_t * p) -{ - hash_pair_t *hp; - int i; - u8 **keys = 0; - - vec_free (p->name); - - pool_free (p->kvp); - - /* *INDENT-OFF* */ - hash_foreach_pair (hp, p->overflow_hash, - ({ - vec_add1 (keys, (u8 *)hp->key); - })); - /* *INDENT-ON* */ - hash_free (p->overflow_hash); - for (i = 0; i < vec_len (keys); i++) - vec_free (keys[i]); - vec_free (keys); -} - -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vppinfra/test_pfhash.c b/src/vppinfra/test_pfhash.c deleted file mode 100644 index ddbdbb34be5..00000000000 --- a/src/vppinfra/test_pfhash.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - Copyright (c) 2013 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 <vppinfra/pfhash.h> -#include <vppinfra/format.h> -#include <vppinfra/random.h> - -#if defined(CLIB_HAVE_VEC128) && ! defined (__ALTIVEC__) - -int verbose = 0; - -always_inline u8 * -random_aligned_string (u32 * seed, uword len) -{ - u8 *alphabet = (u8 *) "abcdefghijklmnopqrstuvwxyz"; - u8 *s = 0; - word i; - - vec_resize_aligned (s, len, 16); - for (i = 0; i < len; i++) - s[i] = alphabet[random_u32 (seed) % 26]; - - return s; -} - -void exit (int); - -int -test_pfhash_main (unformat_input_t * input) -{ - u32 seed = 0xdeaddabe; - int i, iter; - u32 nkeys = 4; - u32 niter = 1; - u32 nbuckets = 1; - u32 bucket; - u32 sizes[3] = { 16, 8, 4 }, this_size, size; - u8 **keys = 0; - pfhash_t _rec, *p = &_rec; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "seed %d", &seed)) - ; - else if (unformat (input, "niter %d", &niter)) - ; - else if (unformat (input, "nkeys %d", &nkeys)) - ; - else if (unformat (input, "nbuckets %d", &nbuckets)) - ; - else if (unformat (input, "verbose %d", &verbose)) - ; - else if (unformat (input, "verbose")) - verbose = 1; - else - clib_error ("unknown input `%U'", format_unformat_error, input); - } - - vec_validate (keys, nkeys - 1); - - for (i = 0; i < nkeys; i++) - { - int j, k; - - again: - keys[i] = random_aligned_string (&seed, 16); - for (j = 0; j < (i - 1); j++) - { - /* Make sure we don't have a dup key in the min key size */ - for (k = 0; k < 4; k++) - { - if (keys[i][k] != keys[j][k]) - goto check_next_key; - } - vec_free (keys[i]); - goto again; - check_next_key: - ; - } - } - - /* test 8 byte key, 8 byte value case separately */ - - for (size = 8; size < 9; size++) - { - this_size = 8; - - fformat (stdout, "%d-byte key 8 byte value test\n", this_size); - - pfhash_init (p, "test", 8 /* key size */ , 8 /* value size */ , - nbuckets + 1); - - for (iter = 0; iter < niter; iter++) - { - bucket = 0; - for (i = 0; i < nkeys; i++) - { - bucket = (i % nbuckets) + 1; - pfhash_set (p, bucket, keys[i], - (void *) (u64) 0x100000000ULL + i + 1); - } - - for (i = 0; i < nkeys; i++) - { - bucket = (i % nbuckets) + 1; - if (pfhash_get (p, bucket, keys[i]) - != (u64) 0x100000000ULL + i + 1) - { - clib_warning ("key %d bucket %d lookup FAIL\n", i, bucket); - (void) pfhash_get (p, bucket, keys[i]); - } - } - - /* test inline functions */ - for (i = 0; i < nkeys; i++) - { - u32 bucket_contents; - u64 value = 0xdeadbeef; - bucket = (i % nbuckets) + 1; - - pfhash_prefetch_bucket (p, bucket); - bucket_contents = pfhash_read_bucket_prefetch_kv (p, bucket); - - value = pfhash_search_kv_8v8 (p, bucket_contents, - (u64 *) keys[i]); - if (value != (u64) 0x100000000ULL + i + 1) - clib_warning ("key %d bucket %d lookup FAIL\n", i, bucket); - } - - if (verbose) - fformat (stdout, "%U\n", format_pfhash, p, verbose > 1); - - for (i = 0; i < nkeys; i++) - { - bucket = (i % nbuckets) + 1; - pfhash_unset (p, bucket, keys[i]); - } - - for (i = 0; i < nkeys; i++) - { - bucket = (i % nbuckets) + 1; - if (pfhash_get (p, bucket, keys[i]) != (u64) ~ 0) - { - clib_warning ("key %d bucket %d lookup FAIL\n", i, bucket); - (void) pfhash_get (p, bucket, keys[i]); - } - } - /* test inline functions */ - for (i = 0; i < nkeys; i++) - { - u32 bucket_contents; - u64 value = 0xdeadbeef; - bucket = (i % nbuckets) + 1; - - pfhash_prefetch_bucket (p, bucket); - bucket_contents = pfhash_read_bucket_prefetch_kv (p, bucket); - - value = pfhash_search_kv_8v8 (p, bucket_contents, - (u64 *) keys[i]); - - if (value != (u64) ~ 0) - clib_warning ("key %d bucket %d lookup FAIL\n", i, bucket); - } - } - pfhash_free (p); - } - - /* test other cases */ - - for (size = 0; size < ARRAY_LEN (sizes); size++) - { - this_size = sizes[size]; - - fformat (stdout, "%d-byte key test\n", this_size); - - pfhash_init (p, "test", this_size, 4 /* value size */ , nbuckets + 1); - - for (iter = 0; iter < niter; iter++) - { - bucket = 0; - for (i = 0; i < nkeys; i++) - { - bucket = (i % nbuckets) + 1; - pfhash_set (p, bucket, keys[i], (void *) (u64) i + 1); - } - - for (i = 0; i < nkeys; i++) - { - bucket = (i % nbuckets) + 1; - if (pfhash_get (p, bucket, keys[i]) != i + 1) - { - clib_warning ("key %d bucket %d lookup FAIL\n", i, bucket); - (void) pfhash_get (p, bucket, keys[i]); - } - } - - /* test inline functions */ - for (i = 0; i < nkeys; i++) - { - u32 bucket_contents; - u32 value = 0xdeadbeef; - bucket = (i % nbuckets) + 1; - - pfhash_prefetch_bucket (p, bucket); - bucket_contents = pfhash_read_bucket_prefetch_kv (p, bucket); - switch (p->key_size) - { - case 16: - value = - pfhash_search_kv_16 (p, bucket_contents, - (u32x4 *) keys[i]); - break; - case 8: - value = - pfhash_search_kv_8 (p, bucket_contents, (u64 *) keys[i]); - break; - case 4: - value = - pfhash_search_kv_4 (p, bucket_contents, (u32 *) keys[i]); - break; - } - - if (value != (i + 1)) - clib_warning ("key %d bucket %d lookup FAIL\n", i, bucket); - } - - if (verbose) - fformat (stdout, "%U\n", format_pfhash, p, verbose > 1); - - for (i = 0; i < nkeys; i++) - { - bucket = (i % nbuckets) + 1; - pfhash_unset (p, bucket, keys[i]); - } - - for (i = 0; i < nkeys; i++) - { - bucket = (i % nbuckets) + 1; - if (pfhash_get (p, bucket, keys[i]) != (u64) ~ 0) - { - clib_warning ("key %d bucket %d lookup FAIL\n", i, bucket); - (void) pfhash_get (p, bucket, keys[i]); - } - } - /* test inline functions */ - for (i = 0; i < nkeys; i++) - { - u32 bucket_contents; - u32 value = 0xdeadbeef; - bucket = (i % nbuckets) + 1; - - pfhash_prefetch_bucket (p, bucket); - bucket_contents = pfhash_read_bucket_prefetch_kv (p, bucket); - switch (p->key_size) - { - case 16: - value = - pfhash_search_kv_16 (p, bucket_contents, - (u32x4 *) keys[i]); - break; - case 8: - value = - pfhash_search_kv_8 (p, bucket_contents, (u64 *) keys[i]); - break; - case 4: - value = - pfhash_search_kv_4 (p, bucket_contents, (u32 *) keys[i]); - break; - } - if (value != (u32) ~ 0) - clib_warning ("key %d bucket %d lookup FAIL\n", i, bucket); - } - } - pfhash_free (p); - } - - exit (0); -} -#else -int -test_pfhash_main (unformat_input_t * input) -{ - clib_warning ("MMX unit not available"); - return 0; -} -#endif - -#ifdef CLIB_UNIX -int -main (int argc, char *argv[]) -{ - unformat_input_t i; - int ret; - - unformat_init_command_line (&i, argv); - ret = test_pfhash_main (&i); - unformat_free (&i); - - return ret; -} -#endif /* CLIB_UNIX */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vppinfra/test_pool.c b/src/vppinfra/test_pool.c deleted file mode 100644 index 67a5e50a38a..00000000000 --- a/src/vppinfra/test_pool.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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. - */ -/* - Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/mem.h> -#include <vppinfra/pool.h> - -#ifdef __KERNEL__ -#include <linux/unistd.h> -#else -#include <unistd.h> -#endif - -int -main (int argc, char *argv[]) -{ - int i, n, seed; - - int *p = 0, *e, j, *o = 0; - - n = atoi (argv[1]); - seed = getpid (); - srandom (1); - - for (i = 0; i < n; i++) - { - if (vec_len (o) < 10 || (random () & 1)) - { - pool_get (p, e); - j = e - p; - *e = j; - vec_add1 (o, j); - } - else - { - j = random () % vec_len (o); - e = p + j; - pool_put (p, e); - vec_delete (o, 1, j); - } - } - p = pool_free (p); - vec_free (o); - return 0; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ |