/* * 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 #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\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
import socket

from scapy.layers.inet import IP, UDP, ICMP
from scapy.layers.inet6 import IPv6
from scapy.layers.l2 import Ether, GRE
from scapy.packet import Raw

from framework import VppTestCase
from util import ppp
from vpp_ip_route import VppIpInterfaceAddress, VppIpRoute, VppRoutePath
from vpp_neighbor import VppNeighbor

""" TestPing is a subclass of  VPPTestCase classes.

Basic test for sanity check of the ping.

"""


class TestPing(VppTestCase):
    """ Ping Test Case """

    @classmethod
    def setUpClass(cls):
        super(TestPing, cls).setUpClass()
        try:
            cls.create_pg_interfaces(range(2))
            cls.interfaces = list(cls.pg_interfaces)

            for i in cls.interfaces:
                i.admin_up()
                i.config_ip4()
                i.config_ip6()
                i.disable_ipv6_ra()
                i.resolve_arp()
                i.resolve_ndp()
        except Exception:
            super(TestPing, cls).tearDownClass()
            raise

    @classmethod
    def tearDownClass(cls):
        super(TestPing, cls).tearDownClass()

    def tearDown(self):
        super(TestPing, self).tearDown()

    def show_commands_at_teardown(self):
        self.logger.info(self.vapi.cli("show hardware"))

    def verify_ping_request(self, p, src, dst, seq):
        ip = p[IP]
        self.assertEqual(ip.version, 4)
        self