#!/usr/bin/env python3

import unittest

import scapy.compat
from scapy.packet import Raw
from scapy.layers.l2 import Ether, Dot1Q, GRE
from scapy.layers.inet import IP, UDP
from scapy.layers.inet6 import IPv6
from scapy.volatile import RandMAC, RandIP

from framework import tag_fixme_vpp_workers
from framework import VppTestCase, VppTestRunner
from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
from vpp_gre_interface import VppGreInterface
from vpp_teib import VppTeib
from vpp_ip import DpoProto
from vpp_ip_route import (
    VppIpRoute,
    VppRoutePath,
    VppIpTable,
    FibPathProto,
    VppMplsLabel,
)
from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface
from util import ppp, ppc
from vpp_papi import VppEnum


@tag_fixme_vpp_workers
class TestGREInputNodes(VppTestCase):
    """GRE Input Nodes Test Case"""

    def setUp(self):
        super(TestGREInputNodes, self).setUp()

        # create 3 pg interfaces - set one in a non-default table.
        self.create_pg_interfaces(range(1))

        for i in self.pg_interfaces:
            i.admin_up()
            i.config_ip4()

    def tearDown(self):
        for i in self.pg_interfaces:
            i.unconfig_ip4()
            i.admin_down()
        super(TestGREInputNodes, self).tearDown()

    def test_gre_input_node(self):
        """GRE gre input nodes not registerd unless configured"""
        pkt = (
            Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
            / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
            / GRE()
        )

        self.pg0.add_stream(pkt)
        self.pg_start()
        # no tunnel created, gre-input not registered
        err = self.statistics.get_counter("/err/ip4-local/unknown_protocol")[0]
        self.assertEqual(err, 1)
        err_count = err

        # create gre tunnel
        gre_if = VppGreInterface(self, self.pg0.local_ip4, "1.1.1.2")
        gre_if.add_vpp_config()

        self.pg0.add_stream(pkt)
        self.pg_start()
        # tunnel created, gre-input registered
        err = self.statistics.get_counter("/err/ip4-local/unknown_protocol")[0]
        # expect no new errors
        self.assertEqual(err, err_count)


class TestGRE(VppTestCase):
    """GRE Test Case"""

    @classmethod
    def setUpClass(cls):
        super(TestGRE, cls).setUpClass()

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

    def setUp(self):
        super(TestGRE, self).setUp()

        # create 3 pg interfaces - set one in a non-default table.
        self.create_pg_interfaces(range(5))

        self.tbl = VppIpTable(self, 1)
        self.tbl.add_vpp_config()
        self.pg1.set_table_ip4(1)

        for i in self.pg_interfaces:
            i.admin_up()

        self.pg0.config_ip4()
        self.pg0.resolve_arp()
        self.pg1.config_ip4()
        self.pg1.resolve_arp()
        self.pg2.config_ip6()
        self.pg2.resolve_ndp()
        self.pg3.config_ip4()
        self.pg3.resolve_arp()
        self.pg4.config_ip4()
        self.pg4.resolve_arp()

    def tearDown(self):
        for i in self.pg_interfaces:
            i.unconfig_ip4()
            i.unconfig_ip6()
            i.admin_down()
        self.pg1.set_table_ip4(0)
        super(TestGRE, self).tearDown()

    def create_stream_ip4(self, src_if, src_ip, dst_ip, dscp=0, ecn=0):
        pkts = []
        tos = (dscp << 2) | ecn
        for i in range(0, 257):
            info = self.create_packet_info(src_if, src_if)
            payload = self.info_to_payload(info)
            p = (
                Ether(dst=src_if.local_mac, src=src_if.remote_mac)
                / IP(src=src_ip, dst=dst_ip, tos=tos)
                / UDP(sport=1234, dport=1234)
                / Raw(payload)
            )
            info.data = p.copy()
            pkts.append(p)
        return pkts

    def create_stream_ip6(self, src_if, src_ip, dst_ip, dscp=0, ecn=0):
        pkts = []
        tc = (dscp << 2) | ecn
        for i in range(0, 257):
            info = self.create_packet_info(src_if, src_if)
            payload = self.info_to_payload(info)
            p = (
                Ether(dst=src_if.local_mac, src=src_if.remote_mac)
                / IPv6(src=src_ip, dst=dst_ip, tc=tc)
                / UDP(sport=1234, dport=1234)
                / Raw(payload)
            )
            info.data = p.copy()
            pkts.append(p)
        return pkts

    def create_tunnel_stream_4o4(self, src_if, tunnel_src, tunnel_dst, src_ip, dst_ip):
        pkts = []
        for i in range(0, 257):
            info = self.create_packet_info(src_if, src_if)
            payload = self.info_to_payload(info)
            p = (
                Ether(dst=src_if.local_mac, src=src_if.remote_mac)
                / IP(src=tunnel_src, dst=tunnel_dst)
                / GRE()
                / IP(src=src_ip, dst=dst_ip)
                / UDP(sport=1234, dport=1234)
                / Raw(payload)
            )
            info.data = p.copy()
            pkts.append(p)
        return pkts

    def create_tunnel_stream_6o4(self, src_if, tunnel_src, tunnel_dst, src_ip, dst_ip):
        pkts = []
        for i in range(0, 257):
            info = self.create_packet_info(src_if, src_if)
            payload = self.info_to_payload(info)
            p = (
                Ether(dst=src_if.local_mac, src=src_if.remote_mac)
                / IP(src=tunnel_src, dst=tunnel_dst)
                / GRE()
                / IPv6(src=src_ip, dst=dst_ip)
                / UDP(sport=1234, dport=1234)
                / Raw(payload)
            )
            info.data = p.copy()
            pkts.append(p)
        return pkts

    def create_tunnel_stream_6o6(self, src_if, tunnel_src, tunnel_dst, src_ip, dst_ip):
        pkts = []
        for i in range(0, 257):
            info = self.create_packet_info(src_if, src_if)
            payload = self.info_to_payload(info)
            p = (
                Ether(dst=src_if.local_mac, src=src_if.remote_mac)
                / IPv6(src=tunnel_src, dst=tunnel_dst)
                / GRE()
                / IPv6(src=src_ip, dst=dst_ip)
                / UDP(sport=1234, dport=1234)
                / Raw(payload)
            )
            info.data = p.copy()
            pkts.append(p)
        return pkts

    def create_tunnel_stream_l2o4(self, src_if, tunnel_src, tunnel_dst):
        pkts = []
        for i in range(0, 257):
            info = self.create_packet_info(src_if, src_if)
            payload = self.info_to_payload(info)
            p = (
                Ether(dst=src_if.local_mac, src=src_if.remote_mac)
                / IP(src=tunnel_src, dst=tunnel_dst)
                / GRE()
                / Ether(dst=RandMAC("*:*:*:*:*:*"), src=RandMAC("*:*:*:*:*:*"))
                / IP(src=scapy.compat.raw(RandIP()), dst=scapy.compat.raw(RandIP()))
                / UDP(sport=1234, dport=1234)
                / Raw(payload)
            )
            info.data = p.copy()
            pkts.append(p)
        return pkts

    def create_tunnel_stream_vlano4(self, src_if, tunnel_src, tunnel_dst, vlan):
        pkts = []
        for i in range(0, 257):
            info = self.create_packet_info(src_if, src_if)
            payload = self.info_to_payload(info)
            p = (
                Ether(dst=src_if.local_mac, src=src_if.remote_mac)
                / IP(src=tunnel_src, dst=tunnel_dst)
                / GRE()
                / Ether(dst=RandMAC("*:*:*:*:*:*"), src=RandMAC("*:*:*:*:*:*"))
                / Dot1Q(vlan=vlan)
                / IP(src=scapy.compat.raw(RandIP()), dst=scapy.compat.raw(RandIP()))
                / UDP(sport=1234, dport=1234)
                / Raw(payload)
            )
            info.data = p.copy()
            pkts.append(p)
        return pkts

    def verify_tunneled_4o4(
        self, src_if, capture, sent, tunnel_src, tunnel_dst, dscp=0, ecn=0
    ):

        self.assertEqual(len(capture), len(sent))
        tos = (dscp << 2) | ecn

        for i in range(len(capture)):
            try:
                tx = sent[i]
                rx = capture[i]

                tx_ip = tx[IP]
                rx_ip = rx[IP]

                s<style>.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */</style><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">socket</span>

<span class="kn">from</span> <span class="nn">scapy.layers.inet</span> <span class="kn">import</span> <span class="n">IP</span><span class="p">,</span> <span class="n">UDP</span><span class="p">,</span> <span class="n">ICMP</span>
<span class="kn">from</span> <span class="nn">scapy.layers.inet6</span> <span class="kn">import</span> <span class="n">IPv6</span>
<span class="kn">from</span> <span class="nn">scapy.layers.l2</span> <span class="kn">import</span> <span class="n">Ether</span><span class="p">,</span> <span class="n">GRE</span>
<span class="kn">from</span> <span class="nn">scapy.packet</span> <span class="kn">import</span> <span class="n">Raw</span>

<span class="kn">from</span> <span class="nn">framework</span> <span class="kn">import</span> <span class="n">VppTestCase</span>
<span class="kn">from</span> <span class="nn">util</span> <span class="kn">import</span> <span class="n">ppp</span>

<span class="sd">&quot;&quot;&quot; TestPing is a subclass of  VPPTestCase classes.</span>

<span class="sd">Basic test for sanity check of the ping.</span>

<span class="sd">&quot;&quot;&quot;</span>


<span class="k">class</span> <span class="nc">TestPing</span><span class="p">(</span><span class="n">VppTestCase</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot; Ping Test Case &quot;&quot;&quot;</span>

    <span class="nd">@classmethod</span>
    <span class="k">def</span> <span class="nf">setUpClass</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
        <span class="nb">super</span><span class="p">(</span><span class="n">TestPing</span><span class="p">,</span> <span class="bp">cls</span><span class="p">)</span><span class="o">.</span><span class="n">setUpClass</span><span class="p">()</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="bp">cls</span><span class="o">.</span><span class="n">create_pg_interfaces</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">))</span>
            <span class="bp">cls</span><span class="o">.</span><span class="n">interfaces</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="bp">cls</span><span class="o">.</span><span class="n">pg_interfaces</span><span class="p">)</span>

            <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">interfaces</span><span class="p">:</span>
                <span class="n">i</span><span class="o">.</span><span class="n">admin_up</span><span class="p">()</span>
                <span class="n">i</span><span class="o">.</span><span class="n">config_ip4</span><span class="p">()</span>
                <span class="n">i</span><span class="o">.</span><span class="n">config_ip6</span><span class="p">()</span>
                <span class="n">i</span><span class="o">.</span><span class="n">disable_ipv6_ra</span><span class="p">()</span>
                <span class="n">i</span><span class="o">.</span><span class="n">resolve_arp</span><span class="p">()</span>
                <span class="n">i</span><span class="o">.</span><span class="n">resolve_ndp</span><span class="p">()</span>
        <span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
            <span class="nb">super</span><span class="p">(</span><span class="n">TestPing</span><span class="p">,</span> <span class="bp">cls</span><span class="p">)</span><span class="o">.</span><span class="n">tearDownClass</span><span class="p">()</span>
            <span class="k">raise</span>

    <span class="k">def</span> <span class="nf">tearDown</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="nb">super</span><span class="p">(</span><span class="n">TestPing</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">tearDown</span><span class="p">()</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">vpp_dead</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">vapi</span><span class="o">.</span><span class="n">cli</span><span class="p">(</span><span class="s2">&quot;show hardware&quot;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">test_ping_basic</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; basic ping test &quot;&quot;&quot;</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">pg_enable_capture</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">pg_interfaces</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">pg_start</span><span class="p">()</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">vapi</span><span class="o">.</span><span class="n">cli</span><span class="p">(</span><span class="s2">&quot;show ip arp&quot;</span><span class="p">))</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">vapi</span><span class="o">.</span><span class="n">cli</span><span class="p">(</span><span class="s2">&quot;show ip6 neighbors&quot;</span><span class="p">))</span>

            <span class="n">remote_ip4</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">pg1</span><span class="o">.</span><span class="n">remote_ip4</span>
            <span class="n">ping_cmd</span> <span class="o">=</span> <span class="s2">&quot;ping &quot;</span> <span class="o">+</span> <span class="n">remote_ip4</span> <span class="o">+</span> <span class="s2">&quot; interval 0.01 repeat 10&quot;</span>
            <span class="n">ret</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">vapi</span><span class="o">.</span><span class="n">cli</span><span class="p">(</span><span class="n">ping_cmd</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="n">ret</span><span class="p">)</span>
            <span class="n">out</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">pg1</span><span class="o">.</span><span class="n">get_capture</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
            <span class="n">icmp_id</span> <span class="o">=</span> <span class="bp">None</span>
            <span class="n">icmp_seq</span> <span class="o">=</span> <span class="mi">1</span>
            <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">out</span><span class="p">:</span>
                <span class="n">ip</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">IP</span><span class="p">]</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">ip</span><span class="o">.</span><span class="n">version</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">ip</span><span class="o">.</span><span class="n">flags</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">ip</span><span class="o">.</span><span class="n">src</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">pg1</span><span class="o">.</span><span class="n">local_ip4</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">ip</span><span class="o">.</span><span class="n">dst</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">pg1</span><span class="o">.</span><span class="n">remote_ip4</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">ip</span><span class="o">.</span><span class="n">proto</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">ip</span><span class="o">.</span><span class="n">options</span><span class="p">),</span> <span class="mi">0</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertGreaterEqual</span><span class="p">(</span><span class="n">ip</span><span class="o">.</span><span class="n">ttl</span><span class="p">,</span> <span class="mi">254</span><span class="p">)</span>
                <span class="n">icmp</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">ICMP</span><span class="p">]</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">icmp</span><span class="o">.</span><span class="n">type</span><span class="p">,</span> <span class="mi">8</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">icmp</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">icmp</span><span class="o">.</span><span class="n">seq</span><span class="p">,</span> <span class="n">icmp_seq</span><span class="p">)</span>
                <span class="n">icmp_seq</span> <span class="o">=</span> <span class="n">icmp_seq</span> <span class="o">+</span> <span class="mi">1</span>
                <span class="k">if</span> <span class="n">icmp_id</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
                    <span class="n">icmp_id</span> <span class="o">=</span> <span class="n">icmp</span><span class="o">.</span><span class="n">id</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">icmp</span><span class="o">.</span><span class="n">id</span><span class="p">,</span> <span class="n">icmp_id</span><span class="p">)</span>
        <span class="k">finally</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">vapi</span><span class="o">.</span><span class="n">cli</span><span class="p">(</span><span class="s2">&quot;show error&quot;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">test_ping_burst</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; burst ping test &quot;&quot;&quot;</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">pg_enable_capture</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">pg_interfaces</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">pg_start</span><span class="p">()</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">vapi</span><span class="o">.</span><span class="n">cli</span><span class="p">(</span><span class="s2">&quot;show ip arp&quot;</span><span class="p">))</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">vapi</span><span class="o">.</span><span class="n">cli</span><span class="p">(</span><span class="s2">&quot;show ip6 neighbors&quot;</span><span class="p">))</span>

            <span class="n">remote_ip4</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">pg1</span><span class="o">.</span><span class="n">remote_ip4</span>
            <span class="n">ping_cmd</span> <span class="o">=</span> <span class="s2">&quot;ping &quot;</span> <span class="o">+</span> <span class="n">remote_ip4</span> <span class="o">+</span> <span class="s2">&quot; interval 0.01 burst 3&quot;</span>
            <span class="n">ret</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">vapi</span><span class="o">.</span><span class="n">cli</span><span class="p">(</span><span class="n">ping_cmd</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="n">ret</span><span class="p">)</span>
            <span class="n">out</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">pg1</span><span class="o">.</span><span class="n">get_capture</span><span class="p">(</span><span class="mi">3</span><span class="o">*</span><span class="mi">5</span><span class="p">)</span>
            <span class="n">icmp_id</span> <span class="o">=</span> <span class="bp">None</span>
            <span class="n">icmp_seq</span> <span class="o">=</span> <span class="mi">1</span>
            <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span>
            <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">out</span><span class="p">:</span>
                <span class="n">ip</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">IP</span><span class="p">]</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">ip</span><span class="o">.</span><span class="n">version</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">ip</span><span class="o">.</span><span class="n">flags</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">ip</span><span class="o">.</span><span class="n">src</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">pg1</span><span class="o">.</span><span class="n">local_ip4</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">ip</span><span class="o">.</span><span class="n">dst</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">pg1</span><span class="o">.</span><span class="n">remote_ip4</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">ip</span><span class="o">.</span><span class="n">proto</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">ip</span><span class="o">.</span><span class="n">options</span><span class="p">),</span> <span class="mi">0</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertGreaterEqual</span><span class="p">(</span><span class="n">ip</span><span class="o">.</span><span class="n">ttl</span><span class="p">,</span> <span class="mi">254</span><span class="p">)</span>
                <span class="n">icmp</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">ICMP</span><span class="p">]</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">icmp</span><span class="o">.</span><span class="n">type</span><span class="p">,</span> <span class="mi">8</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">icmp</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">icmp</span><span class="o">.</span><span class="n">seq</span><span class="p">,</span> <span class="n">icmp_seq</span><span class="p">)</span>
                <span class="n">count</span> <span class="o">=</span> <span class="n">count</span> <span class="o">+</span> <span class="mi">1</span>
                <span class="k">if</span> <span class="n">count</span> <span class="o">&gt;=</span> <span class="mi">3</span><span class="p">:</span>
                    <span class="n">icmp_seq</span> <span class="o">=</span> <span class="n">icmp_seq</span> <span class="o">+</span> <span class="mi">1</span>
                    <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span>
                <span class="k">if</span> <span class="n">icmp_id</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
                    <span class="n">icmp_id</span> <span class="o">=</span> <span class="n">icmp</span><span class="o">.</span><span class="n">id</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">icmp</span><span class="o">.</span><span class="n">id</span><span class="p">,</span> <span class="n">icmp_id</span><span class="p">)</span>
        <span class="k">finally</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">vapi</span><span class="o">.</span><span class="n">cli</span><span class="p">(</span><span class="s2">&quot;show error&quot;</span><span class="p">)</span>
</pre></div>
</code></pre></td></tr></table>
</div> <!-- class=content -->
<div id="lfcollabprojects-footer">
  <div class="gray-diagonal">
    <div class="footer-inner">
      <p>
        &copy; 2016 <a href="https://www.fd.io/">FD.io</a> a Linux Foundation
        Collaborative Project. All Rights Reserved.
      </p>
      <p>
        Linux Foundation is a registered trademark of The Linux Foundation.
        Linux is a registered
        <a
          href="http://www.linuxfoundation.org/programs/legal/trademark"
          title="Linux Mark Institute"
          >trademark</a
        >
        of Linus Torvalds.
      </p>
      <p>
        Please see our
        <a href="http://www.linuxfoundation.org/privacy">privacy policy</a> and
        <a href="http://www.linuxfoundation.org/terms">terms of use</a>
      </p>
    </div>
  </div>
</div>
</div> <!-- id=cgit -->
</body>
</html>
.0.0", gre_if.sw_if_index)]
        )
        route_via_tun_2.add_vpp_config()

        tx = self.create_stream_ip4(self.pg0, "2.2.2.3", "2.2.2.2")
        rx = self.send_and_expect(self.pg0, tx, self.pg1)
        self.verify_tunneled_4o4(self.pg1, rx, tx, self.pg0.local_ip4, "1.1.1.2")

        #
        # cleanup
        #
        route_via_tun_2.remove_vpp_config()
        gre_if.remove_vpp_config()

    def test_mgre(self):
        """mGRE IPv4 tunnel Tests"""

        for itf in self.pg_interfaces[3:]:
            #
            # one underlay nh for each overlay/tunnel peer
            #
            itf.generate_remote_hosts(4)
            itf.configure_ipv4_neighbors()

            #
            # Create an L3 GRE tunnel.
            #  - set it admin up
            #  - assign an IP Addres
            #  - Add a route via the tunnel
            #
            gre_if = VppGreInterface(
                self,
                itf.local_ip4,
                "0.0.0.0",
                mode=(VppEnum.vl_api_tunnel_mode_t.TUNNEL_API_MODE_MP),
            )
            gre_if.add_vpp_config()
            gre_if.admin_up()
            gre_if.config_ip4()
            gre_if.generate_remote_hosts(4)

            self.logger.info(self.vapi.cli("sh adj"))
            self.logger.info(self.vapi.cli("sh ip fib"))

            #
            # ensure we don't match to the tunnel if the source address
            # is all zeros
            #
            tx = self.create_tunnel_stream_4o4(
                self.pg0,
                "0.0.0.0",
                itf.local_ip4,
                self.pg0.local_ip4,
                self.pg0.remote_ip4,
            )
            self.send_and_assert_no_replies(self.pg0, tx)

            #
            # for-each peer
            #
            for ii in range(1, 4):
                route_addr = "4.4.4.%d" % ii
                tx_e = self.create_stream_ip4(self.pg0, "5.5.5.5", route_addr)

                #
                # route traffic via the peer
                #
                route_via_tun = VppIpRoute(
                    self,
                    route_addr,
                    32,
                    [VppRoutePath(gre_if._remote_hosts[ii].ip4, gre_if.sw_if_index)],
                )
                route_via_tun.add_vpp_config()

                # all packets dropped at this point
                rx = self.send_and_assert_no_replies(self.pg0, tx_e)

                gre_if.admin_down()
                gre_if.admin_up()
                rx = self.send_and_assert_no_replies(self.pg0, tx_e)

                #
                # Add a TEIB entry resolves the peer
                #
                teib = VppTeib(
                    self,
                    gre_if,
                    gre_if._remote_hosts[ii].ip4,
                    itf._remote_hosts[ii].ip4,
                )
                teib.add_vpp_config()

                #
                # Send a packet stream that is routed into the tunnel
                #  - packets are GRE encapped
                #
                rx = self.send_and_expect(self.pg0, tx_e, itf)
                self.verify_tunneled_4o4(
                    self.pg0, rx, tx_e, itf.local_ip4, itf._remote_hosts[ii].ip4
                )

                tx_i = self.create_tunnel_stream_4o4(
                    self.pg0,
                    itf._remote_hosts[ii].ip4,
                    itf.local_ip4,
                    self.pg0.local_ip4,
                    self.pg0.remote_ip4,
                )
                rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
                self.verify_decapped_4o4(self.pg0, rx, tx_i)

                #
                # delete and re-add the TEIB
                #
                teib.remove_vpp_config()
                self.send_and_assert_no_replies(self.pg0, tx_e)
                self.send_and_assert_no_replies(self.pg0, tx_i)

                teib.add_vpp_config()
                rx = self.send_and_expect(self.pg0, tx_e, itf)
                self.verify_tunneled_4o4(
                    self.pg0, rx, tx_e, itf.local_ip4, itf._remote_hosts[ii].ip4
                )
                rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
                self.verify_decapped_4o4(self.pg0, rx, tx_i)

                #
                # bounce the interface state and try packets again
                #
                gre_if.admin_down()
                gre_if.admin_up()
                rx = self.send_and_expect(self.pg0, tx_e, itf)
                self.verify_tunneled_4o4(
                    self.pg0, rx, tx_e, itf.local_ip4, itf._remote_hosts[ii].ip4
                )
                rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
                self.verify_decapped_4o4(self.pg0, rx, tx_i)

            gre_if.admin_down()
            gre_if.unconfig_ip4()

    def test_mgre6(self):
        """mGRE IPv6 tunnel Tests"""

        self.pg0.config_ip6()
        self.pg0.resolve_ndp()

        e = VppEnum.vl_api_tunnel_encap_decap_flags_t

        for itf in self.pg_interfaces[3:]:
            #
            # one underlay nh for each overlay/tunnel peer
            #
            itf.config_ip6()
            itf.generate_remote_hosts(4)
            itf.configure_ipv6_neighbors()

            #
            # Create an L3 GRE tunnel.
            #  - set it admin up
            #  - assign an IP Addres
            #  - Add a route via the tunnel
            #
            gre_if = VppGreInterface(
                self,
                itf.local_ip6,
                "::",
                mode=(VppEnum.vl_api_tunnel_mode_t.TUNNEL_API_MODE_MP),
                flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP,
            )

            gre_if.add_vpp_config()
            gre_if.admin_up()
            gre_if.config_ip6()
            gre_if.generate_remote_hosts(4)

            #
            # for-each peer
            #
            for ii in range(1, 4):
                route_addr = "4::%d" % ii

                #
                # Add a TEIB entry resolves the peer
                #
                teib = VppTeib(
                    self,
                    gre_if,
                    gre_if._remote_hosts[ii].ip6,
                    itf._remote_hosts[ii].ip6,
                )
                teib.add_vpp_config()

                #
                # route traffic via the peer
                #
                route_via_tun = VppIpRoute(
                    self,
                    route_addr,
                    128,
                    [VppRoutePath(gre_if._remote_hosts[ii].ip6, gre_if.sw_if_index)],
                )
                route_via_tun.add_vpp_config()

                #
                # Send a packet stream that is routed into the tunnel
                #  - packets are GRE encapped
                #
                tx_e = self.create_stream_ip6(
                    self.pg0, "5::5", route_addr, dscp=2, ecn=1
                )
                rx = self.send_and_expect(self.pg0, tx_e, itf)
                self.verify_tunneled_6o6(
                    self.pg0, rx, tx_e, itf.local_ip6, itf._remote_hosts[ii].ip6, dscp=2
                )
                tx_i = self.create_tunnel_stream_6o6(
                    self.pg0,
                    itf._remote_hosts[ii].ip6,
                    itf.local_ip6,
                    self.pg0.local_ip6,
                    self.pg0.remote_ip6,
                )
                rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
                self.verify_decapped_6o6(self.pg0, rx, tx_i)

                #
                # delete and re-add the TEIB
                #
                teib.remove_vpp_config()
                self.send_and_assert_no_replies(self.pg0, tx_e)

                teib.add_vpp_config()
                rx = self.send_and_expect(self.pg0, tx_e, itf)
                self.verify_tunneled_6o6(
                    self.pg0, rx, tx_e, itf.local_ip6, itf._remote_hosts[ii].ip6, dscp=2
                )
                rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
                self.verify_decapped_6o6(self.pg0, rx, tx_i)

            gre_if.admin_down()
            gre_if.unconfig_ip4()
            itf.unconfig_ip6()
        self.pg0.unconfig_ip6()


if __name__ == "__main__":
    unittest.main(testRunner=VppTestRunner)