tests: refactor. Replace literal constant w/ named constant.
[vpp.git] / test / test_punt.py
index 74dc923..5dec066 100644 (file)
@@ -23,6 +23,11 @@ from scapy.layers.inet6 import IPv6, ICMPv6DestUnreach
 import six
 from framework import VppTestCase, VppTestRunner
 
+from vpp_ip import DpoProto
+from vpp_ip_route import VppIpRoute, VppRoutePath
+
+NUM_PKTS = 67
+
 
 # Format MAC Address
 def get_mac_addr(bytes_addr):
@@ -671,5 +676,178 @@ class TestIP6PuntSocket(TestPuntSocket):
         punts = self.vapi.punt_socket_dump(is_ip6=1)
         self.assertEqual(len(punts), 0)
 
+
+class TestPunt(VppTestCase):
+    """ Punt Test Case """
+
+    @classmethod
+    def setUpClass(cls):
+        super(TestPunt, cls).setUpClass()
+
+    @classmethod
+    def tearDownClass(cls):
+        super(TestPunt, cls).tearDownClass()
+
+    def setUp(self):
+        super(TestPunt, self).setUp()
+
+        self.create_pg_interfaces(range(4))
+
+        for i in self.pg_interfaces:
+            i.admin_up()
+            i.config_ip4()
+            i.resolve_arp()
+            i.config_ip6()
+            i.resolve_ndp()
+
+    def tearDown(self):
+        for i in self.pg_interfaces:
+            i.unconfig_ip4()
+            i.unconfig_ip6()
+            i.ip6_disable()
+            i.admin_down()
+        super(TestPunt, self).tearDown()
+
+    def test_punt(self):
+        """ Excpetion Path testing """
+
+        #
+        # Using the test CLI we will hook in a exception path to
+        # send ACL deny packets out of pg0 and pg1.
+        # the ACL is src,dst = 1.1.1.1,1.1.1.2
+        #
+        ip_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
+                                [VppRoutePath(self.pg3.remote_ip4,
+                                              self.pg3.sw_if_index)])
+        ip_1_1_1_2.add_vpp_config()
+        ip_1_2 = VppIpRoute(self, "1::2", 128,
+                            [VppRoutePath(self.pg3.remote_ip6,
+                                          self.pg3.sw_if_index,
+                                          proto=DpoProto.DPO_PROTO_IP6)],
+                            is_ip6=1)
+        ip_1_2.add_vpp_config()
+
+        p4 = (Ether(src=self.pg2.remote_mac,
+                    dst=self.pg2.local_mac) /
+              IP(src="1.1.1.1", dst="1.1.1.2") /
+              UDP(sport=1234, dport=1234) /
+              Raw('\xa5' * 100))
+        p6 = (Ether(src=self.pg2.remote_mac,
+                    dst=self.pg2.local_mac) /
+              IPv6(src="1::1", dst="1::2") /
+              UDP(sport=1234, dport=1234) /
+              Raw('\xa5' * 100))
+        self.send_and_expect(self.pg2, p4*1, self.pg3)
+        self.send_and_expect(self.pg2, p6*1, self.pg3)
+
+        #
+        # apply the punting features
+        #
+        self.vapi.cli("test punt pg2")
+
+        #
+        # pkts now dropped
+        #
+        self.send_and_assert_no_replies(self.pg2, p4*NUM_PKTS)
+        self.send_and_assert_no_replies(self.pg2, p6*NUM_PKTS)
+
+        #
+        # Check state:
+        #  1 - node error counters
+        #  2 - per-reason counters
+        #    2, 3 are the index of the assigned punt reason
+        #
+        stats = self.statistics.get_counter(
+            "/err/punt-dispatch/No registrations")
+        self.assertEqual(stats, 2*NUM_PKTS)
+
+        stats = self.statistics.get_counter("/net/punt")
+        self.assertEqual(stats[0][7]['packets'], NUM_PKTS)
+        self.assertEqual(stats[0][8]['packets'], NUM_PKTS)
+
+        #
+        # use the test CLI to test a client that punts exception
+        # packets out of pg0
+        #
+        self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip4)
+        self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip6)
+
+        rx4s = self.send_and_expect(self.pg2, p4*NUM_PKTS, self.pg0)
+        rx6s = self.send_and_expect(self.pg2, p6*NUM_PKTS, self.pg0)
+
+        #
+        # check the packets come out IP unmodified but destined to pg0 host
+        #
+        for rx in rx4s:
+            self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
+            self.assertEqual(rx[Ether].src, self.pg0.local_mac)
+            self.assertEqual(p4[IP].dst, rx[IP].dst)
+            self.assertEqual(p4[IP].ttl, rx[IP].ttl)
+        for rx in rx6s:
+            self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
+            self.assertEqual(rx[Ether].src, self.pg0.local_mac)
+            self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
+            self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
+
+        stats = self.statistics.get_counter("/net/punt")
+        self.assertEqual(stats[0][7]['packets'], 2*NUM_PKTS)
+        self.assertEqual(stats[0][8]['packets'], 2*NUM_PKTS)
+
+        #
+        # add another registration for the same reason to send packets
+        # out of pg1
+        #
+        self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip4)
+        self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip6)
+
+        self.vapi.cli("clear trace")
+        self.pg2.add_stream(p4 * NUM_PKTS)
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+
+        rxd = self.pg0.get_capture(NUM_PKTS)
+        for rx in rxd:
+            self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
+            self.assertEqual(rx[Ether].src, self.pg0.local_mac)
+            self.assertEqual(p4[IP].dst, rx[IP].dst)
+            self.assertEqual(p4[IP].ttl, rx[IP].ttl)
+        rxd = self.pg1.get_capture(NUM_PKTS)
+        for rx in rxd:
+            self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
+            self.assertEqual(rx[Ether].src, self.pg1.local_mac)
+            self.assertEqual(p4[IP].dst, rx[IP].dst)
+            self.assertEqual(p4[IP].ttl, rx[IP].ttl)
+
+        self.vapi.cli("clear trace")
+        self.pg2.add_stream(p6 * NUM_PKTS)
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+
+        rxd = self.pg0.get_capture(NUM_PKTS)
+        for rx in rxd:
+            self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
+            self.assertEqual(rx[Ether].src, self.pg0.local_mac)
+            self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
+            self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
+        rxd = self.pg1.get_capture(NUM_PKTS)
+        for rx in rxd:
+            self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
+            self.assertEqual(rx[Ether].src, self.pg1.local_mac)
+            self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
+            self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
+
+        stats = self.statistics.get_counter("/net/punt")
+        self.assertEqual(stats[0][7]['packets'], 3*NUM_PKTS)
+        self.assertEqual(stats[0][8]['packets'], 3*NUM_PKTS)
+
+        self.logger.info(self.vapi.cli("show vlib graph punt-dispatch"))
+        self.logger.info(self.vapi.cli("show punt client"))
+        self.logger.info(self.vapi.cli("show punt reason"))
+        self.logger.info(self.vapi.cli("show punt stats"))
+        self.logger.info(self.vapi.cli("show punt db"))
+
+        self.vapi.cli("test punt clear")
+
+
 if __name__ == '__main__':
     unittest.main(testRunner=VppTestRunner)