ip: change icmp4 throttle
[vpp.git] / test / test_geneve.py
index ebe95a0..f6886c6 100644 (file)
@@ -1,19 +1,22 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 import socket
 
 import socket
-from util import ip4n_range, ip4_range
+from util import ip4_range
 import unittest
 from framework import VppTestCase, VppTestRunner
 from template_bd import BridgeDomain
 
 import unittest
 from framework import VppTestCase, VppTestRunner
 from template_bd import BridgeDomain
 
-from scapy.layers.l2 import Ether
-from scapy.layers.inet import IP, UDP
-from scapy.layers.geneve import GENEVE
-from scapy.utils import atol
+from scapy.layers.l2 import Ether, ARP
+from scapy.layers.inet import IP, UDP, ICMP
+from scapy.contrib.geneve import GENEVE
+
+import util
+from vpp_ip_route import VppIpRoute, VppRoutePath
+from vpp_ip import INVALID_INDEX
 
 
 class TestGeneve(BridgeDomain, VppTestCase):
 
 
 class TestGeneve(BridgeDomain, VppTestCase):
-    """ GENEVE Test Case """
+    """GENEVE Test Case"""
 
     def __init__(self, *args):
         BridgeDomain.__init__(self)
 
     def __init__(self, *args):
         BridgeDomain.__init__(self)
@@ -25,14 +28,16 @@ class TestGeneve(BridgeDomain, VppTestCase):
         Encapsulate the original payload frame by adding GENEVE header with its
         UDP, IP and Ethernet fields
         """
         Encapsulate the original payload frame by adding GENEVE header with its
         UDP, IP and Ethernet fields
         """
-        return (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
-                IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
-                UDP(sport=self.dport, dport=self.dport, chksum=0) /
-                GENEVE(vni=vni) /
-                pkt)
+        return (
+            Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
+            / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
+            / UDP(sport=self.dport, dport=self.dport, chksum=0)
+            / GENEVE(vni=vni)
+            / pkt
+        )
 
     def ip_range(self, start, end):
 
     def ip_range(self, start, end):
-        """ range of remote ip's """
+        """range of remote ip's"""
         return ip4_range(self.pg0.remote_ip4, start, end)
 
     def encap_mcast(self, pkt, src_ip, src_mac, vni):
         return ip4_range(self.pg0.remote_ip4, start, end)
 
     def encap_mcast(self, pkt, src_ip, src_mac, vni):
@@ -40,11 +45,13 @@ class TestGeneve(BridgeDomain, VppTestCase):
         Encapsulate the original payload frame by adding GENEVE header with its
         UDP, IP and Ethernet fields
         """
         Encapsulate the original payload frame by adding GENEVE header with its
         UDP, IP and Ethernet fields
         """
-        return (Ether(src=src_mac, dst=self.mcast_mac) /
-                IP(src=src_ip, dst=self.mcast_ip4) /
-                UDP(sport=self.dport, dport=self.dport, chksum=0) /
-                GENEVE(vni=vni) /
-                pkt)
+        return (
+            Ether(src=src_mac, dst=self.mcast_mac)
+            / IP(src=src_ip, dst=self.mcast_ip4)
+            / UDP(sport=self.dport, dport=self.dport, chksum=0)
+            / GENEVE(vni=vni)
+            / pkt
+        )
 
     def decapsulate(self, pkt):
         """
 
     def decapsulate(self, pkt):
         """
@@ -85,18 +92,21 @@ class TestGeneve(BridgeDomain, VppTestCase):
         # Create 10 ucast geneve tunnels under bd
         ip_range_start = 10
         ip_range_end = ip_range_start + n_ucast_tunnels
         # Create 10 ucast geneve tunnels under bd
         ip_range_start = 10
         ip_range_end = ip_range_start + n_ucast_tunnels
-        next_hop_address = cls.pg0.remote_ip4n
-        for dest_ip4n in ip4n_range(next_hop_address, ip_range_start,
-                                    ip_range_end):
-            # add host route so dest_ip4n will not be resolved
-            cls.vapi.ip_add_del_route(dst_address=dest_ip4n,
-                                      dst_address_length=32,
-                                      next_hop_address=next_hop_address)
+        next_hop_address = cls.pg0.remote_ip4
+        for dest_ip4 in ip4_range(next_hop_address, ip_range_start, ip_range_end):
+            # add host route so dest_ip4 will not be resolved
+            rip = VppIpRoute(
+                cls,
+                dest_ip4,
+                32,
+                [VppRoutePath(next_hop_address, INVALID_INDEX)],
+                register=False,
+            )
+            rip.add_vpp_config()
             r = cls.vapi.geneve_add_del_tunnel(
             r = cls.vapi.geneve_add_del_tunnel(
-                local_address=cls.pg0.local_ip4n, remote_address=dest_ip4n,
-                vni=vni)
-            cls.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index,
-                                                bd_id=vni)
+                local_address=cls.pg0.local_ip4, remote_address=dest_ip4, vni=vni
+            )
+            cls.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index, bd_id=vni)
 
     @classmethod
     def add_del_shared_mcast_dst_load(cls, is_add):
 
     @classmethod
     def add_del_shared_mcast_dst_load(cls, is_add):
@@ -109,11 +119,14 @@ class TestGeneve(BridgeDomain, VppTestCase):
         vni_end = vni_start + n_shared_dst_tunnels
         for vni in range(vni_start, vni_end):
             r = cls.vapi.geneve_add_del_tunnel(
         vni_end = vni_start + n_shared_dst_tunnels
         for vni in range(vni_start, vni_end):
             r = cls.vapi.geneve_add_del_tunnel(
-                local_address=cls.pg0.local_ip4n,
-                remote_address=cls.mcast_ip4n, mcast_sw_if_index=1,
-                is_add=is_add, vni=vni)
-            if r.sw_if_index == 0xffffffff:
-                raise "bad sw_if_index"
+                local_address=cls.pg0.local_ip4,
+                remote_address=cls.mcast_ip4,
+                mcast_sw_if_index=1,
+                is_add=is_add,
+                vni=vni,
+            )
+            if r.sw_if_index == 0xFFFFFFFF:
+                raise ValueError("bad sw_if_index: ~0")
 
     @classmethod
     def add_shared_mcast_dst_load(cls):
 
     @classmethod
     def add_shared_mcast_dst_load(cls):
@@ -131,13 +144,15 @@ class TestGeneve(BridgeDomain, VppTestCase):
         n_distinct_dst_tunnels = 10
         ip_range_start = 10
         ip_range_end = ip_range_start + n_distinct_dst_tunnels
         n_distinct_dst_tunnels = 10
         ip_range_start = 10
         ip_range_end = ip_range_start + n_distinct_dst_tunnels
-        for dest_ip4n in ip4n_range(cls.mcast_ip4n, ip_range_start,
-                                    ip_range_end):
-            vni = bytearray(dest_ip4n)[3]
-            cls.vapi.geneve_add_del_tunnel(local_address=cls.pg0.local_ip4n,
-                                           remote_address=dest_ip4n,
-                                           mcast_sw_if_index=1, is_add=is_add,
-                                           vni=vni)
+        for dest_ip4 in ip4_range(cls.mcast_ip4, ip_range_start, ip_range_end):
+            vni = int(dest_ip4.split(".")[3])
+            cls.vapi.geneve_add_del_tunnel(
+                local_address=cls.pg0.local_ip4,
+                remote_address=dest_ip4,
+                mcast_sw_if_index=1,
+                is_add=is_add,
+                vni=vni,
+            )
 
     @classmethod
     def add_mcast_tunnels_load(cls):
 
     @classmethod
     def add_mcast_tunnels_load(cls):
@@ -171,36 +186,41 @@ class TestGeneve(BridgeDomain, VppTestCase):
             cls.pg0.resolve_arp()
 
             # Our Multicast address
             cls.pg0.resolve_arp()
 
             # Our Multicast address
-            cls.mcast_ip4 = '239.1.1.1'
-            cls.mcast_ip4n = socket.inet_pton(socket.AF_INET, cls.mcast_ip4)
-            iplong = atol(cls.mcast_ip4)
-            cls.mcast_mac = "01:00:5e:%02x:%02x:%02x" % (
-                (iplong >> 16) & 0x7F, (iplong >> 8) & 0xFF, iplong & 0xFF)
+            cls.mcast_ip4 = "239.1.1.1"
+            cls.mcast_mac = util.mcast_ip_to_mac(cls.mcast_ip4)
 
             # Create GENEVE VTEP on VPP pg0, and put geneve_tunnel0 and pg1
             #  into BD.
 
             # Create GENEVE VTEP on VPP pg0, and put geneve_tunnel0 and pg1
             #  into BD.
+            cls.single_tunnel_vni = 0xABCDE
             cls.single_tunnel_bd = 1
             r = cls.vapi.geneve_add_del_tunnel(
             cls.single_tunnel_bd = 1
             r = cls.vapi.geneve_add_del_tunnel(
-                local_address=cls.pg0.local_ip4n,
-                remote_address=cls.pg0.remote_ip4n, vni=cls.single_tunnel_bd)
-            cls.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index,
-                                                bd_id=cls.single_tunnel_bd)
+                local_address=cls.pg0.local_ip4,
+                remote_address=cls.pg0.remote_ip4,
+                vni=cls.single_tunnel_vni,
+            )
+            cls.vapi.sw_interface_set_l2_bridge(
+                rx_sw_if_index=r.sw_if_index, bd_id=cls.single_tunnel_bd
+            )
             cls.vapi.sw_interface_set_l2_bridge(
             cls.vapi.sw_interface_set_l2_bridge(
-                rx_sw_if_index=cls.pg1.sw_if_index, bd_id=cls.single_tunnel_bd)
+                rx_sw_if_index=cls.pg1.sw_if_index, bd_id=cls.single_tunnel_bd
+            )
 
             # Setup vni 2 to test multicast flooding
             cls.n_ucast_tunnels = 10
             cls.mcast_flood_bd = 2
 
             # Setup vni 2 to test multicast flooding
             cls.n_ucast_tunnels = 10
             cls.mcast_flood_bd = 2
-            cls.create_geneve_flood_test_bd(cls.mcast_flood_bd,
-                                            cls.n_ucast_tunnels)
+            cls.create_geneve_flood_test_bd(cls.mcast_flood_bd, cls.n_ucast_tunnels)
             r = cls.vapi.geneve_add_del_tunnel(
             r = cls.vapi.geneve_add_del_tunnel(
-                local_address=cls.pg0.local_ip4n,
-                remote_address=cls.mcast_ip4n, mcast_sw_if_index=1,
-                vni=cls.mcast_flood_bd)
-            cls.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index,
-                                                bd_id=cls.mcast_flood_bd)
+                local_address=cls.pg0.local_ip4,
+                remote_address=cls.mcast_ip4,
+                mcast_sw_if_index=1,
+                vni=cls.mcast_flood_bd,
+            )
             cls.vapi.sw_interface_set_l2_bridge(
             cls.vapi.sw_interface_set_l2_bridge(
-                rx_sw_if_index=cls.pg2.sw_if_index, bd_id=cls.mcast_flood_bd)
+                rx_sw_if_index=r.sw_if_index, bd_id=cls.mcast_flood_bd
+            )
+            cls.vapi.sw_interface_set_l2_bridge(
+                rx_sw_if_index=cls.pg2.sw_if_index, bd_id=cls.mcast_flood_bd
+            )
 
             # Add and delete mcast tunnels to check stability
             cls.add_shared_mcast_dst_load()
 
             # Add and delete mcast tunnels to check stability
             cls.add_shared_mcast_dst_load()
@@ -210,10 +230,10 @@ class TestGeneve(BridgeDomain, VppTestCase):
 
             # Setup vni 3 to test unicast flooding
             cls.ucast_flood_bd = 3
 
             # Setup vni 3 to test unicast flooding
             cls.ucast_flood_bd = 3
-            cls.create_geneve_flood_test_bd(cls.ucast_flood_bd,
-                                            cls.n_ucast_tunnels)
+            cls.create_geneve_flood_test_bd(cls.ucast_flood_bd, cls.n_ucast_tunnels)
             cls.vapi.sw_interface_set_l2_bridge(
             cls.vapi.sw_interface_set_l2_bridge(
-                rx_sw_if_index=cls.pg3.sw_if_index, bd_id=cls.ucast_flood_bd)
+                rx_sw_if_index=cls.pg3.sw_if_index, bd_id=cls.ucast_flood_bd
+            )
         except Exception:
             super(TestGeneve, cls).tearDownClass()
             raise
         except Exception:
             super(TestGeneve, cls).tearDownClass()
             raise
@@ -223,12 +243,94 @@ class TestGeneve(BridgeDomain, VppTestCase):
     #  @param self The object pointer.
     def tearDown(self):
         super(TestGeneve, self).tearDown()
     #  @param self The object pointer.
     def tearDown(self):
         super(TestGeneve, self).tearDown()
-        if not self.vpp_dead:
-            self.logger.info(self.vapi.cli("show bridge-domain 1 detail"))
-            self.logger.info(self.vapi.cli("show bridge-domain 2 detail"))
-            self.logger.info(self.vapi.cli("show bridge-domain 3 detail"))
-            self.logger.info(self.vapi.cli("show geneve tunnel"))
+
+    def show_commands_at_teardown(self):
+        self.logger.info(self.vapi.cli("show bridge-domain 1 detail"))
+        self.logger.info(self.vapi.cli("show bridge-domain 2 detail"))
+        self.logger.info(self.vapi.cli("show bridge-domain 3 detail"))
+        self.logger.info(self.vapi.cli("show geneve tunnel"))
+
+
+class TestGeneveL3(VppTestCase):
+    """GENEVE L3 Test Case"""
+
+    @classmethod
+    def setUpClass(cls):
+        super(TestGeneveL3, 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.resolve_arp()
+        except Exception:
+            super(TestGeneveL3, cls).tearDownClass()
+            raise
+
+    @classmethod
+    def tearDownClass(cls):
+        super(TestGeneveL3, cls).tearDownClass()
+
+    def tearDown(self):
+        super(TestGeneveL3, self).tearDown()
+
+    def show_commands_at_teardown(self):
+        self.logger.info(self.vapi.cli("show geneve tunnel"))
+        self.logger.info(self.vapi.cli("show ip neighbor"))
+
+    def test_l3_packet(self):
+        vni = 1234
+        r = self.vapi.add_node_next(
+            node_name="geneve4-input", next_name="ethernet-input"
+        )
+        r = self.vapi.geneve_add_del_tunnel2(
+            is_add=1,
+            local_address=self.pg0.local_ip4,
+            remote_address=self.pg0.remote_ip4,
+            vni=vni,
+            l3_mode=1,
+            decap_next_index=r.next_index,
+        )
+
+        self.vapi.sw_interface_add_del_address(
+            sw_if_index=r.sw_if_index, prefix="10.0.0.1/24"
+        )
+
+        pkt = (
+            Ether(src=self.pg0.remote_mac, dst="d0:0b:ee:d0:00:00")
+            / IP(src="10.0.0.2", dst="10.0.0.1")
+            / ICMP()
+        )
+
+        encap = (
+            Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
+            / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
+            / UDP(sport=6081, dport=6081, chksum=0)
+            / GENEVE(vni=vni)
+        )
+
+        arp = Ether(src=self.pg0.remote_mac, dst="d0:0b:ee:d0:00:00") / ARP(
+            op="is-at",
+            hwsrc=self.pg0.remote_mac,
+            hwdst="d0:0b:ee:d0:00:00",
+            psrc="10.0.0.2",
+            pdst="10.0.0.1",
+        )
+
+        rx = self.send_and_expect(self.pg0, encap / pkt * 1, self.pg0)
+        rx = self.send_and_assert_no_replies(self.pg0, encap / arp * 1, self.pg0)
+        rx = self.send_and_expect(self.pg0, encap / pkt * 1, self.pg0)
+        self.assertEqual(rx[0][ICMP].type, 0)  # echo reply
+
+        r = self.vapi.geneve_add_del_tunnel2(
+            is_add=0,
+            local_address=self.pg0.local_ip4,
+            remote_address=self.pg0.remote_ip4,
+            vni=vni,
+        )
 
 
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     unittest.main(testRunner=VppTestRunner)
     unittest.main(testRunner=VppTestRunner)