stats: adding symlinks for nodes and interfaces in the stat segment
[vpp.git] / test / test_stats_client.py
index 87c9efd..7e17e2a 100644 (file)
@@ -1,13 +1,16 @@
-#!/usr/bin/env python2.7
+#!/usr/bin/env python3
 
 import unittest
-
 import psutil
 from vpp_papi.vpp_stats import VPPStats
 
+from framework import tag_fixme_vpp_workers
 from framework import VppTestCase, VppTestRunner
+from scapy.layers.l2 import Ether
+from scapy.layers.inet import IP
 
 
+@tag_fixme_vpp_workers
 class StatsClientTestCase(VppTestCase):
     """Test Stats Client"""
 
@@ -19,6 +22,18 @@ class StatsClientTestCase(VppTestCase):
     def tearDownClass(cls):
         super(StatsClientTestCase, cls).tearDownClass()
 
+    @classmethod
+    def setUpConstants(cls):
+        cls.extra_vpp_statseg_config = "per-node-counters on"
+        cls.extra_vpp_statseg_config += "update-interval 0.05"
+        super(StatsClientTestCase, cls).setUpConstants()
+
+    def test_set_errors(self):
+        """Test set errors"""
+        self.assertEqual(self.statistics.set_errors(), {})
+        self.assertEqual(
+            self.statistics.get_counter('/err/ethernet-input/no error'), [0])
+
     def test_client_fd_leak(self):
         """Test file descriptor count - VPP-1486"""
 
@@ -27,7 +42,7 @@ class StatsClientTestCase(VppTestCase):
         initial_fds = p.num_fds()
 
         for _ in range(100):
-            stats = VPPStats(socketname=cls.stats_sock)
+            stats = VPPStats(socketname=cls.get_stats_sock_path())
             stats.disconnect()
 
         ending_fds = p.num_fds()
@@ -37,5 +52,113 @@ class StatsClientTestCase(VppTestCase):
                          "ending client side file descriptor count: %s" % (
                              initial_fds, ending_fds))
 
+    def test_symlink_values(self):
+        """Test symlinks reported values"""
+        self.create_pg_interfaces(range(2))
+
+        for i in self.pg_interfaces:
+            i.admin_up()
+            i.config_ip4()
+            i.resolve_arp()
+
+        p = list()
+        for i in range(5):
+            packet = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
+                      IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4))
+            p.append(packet)
+
+        self.send_and_expect(self.pg0, p, self.pg1)
+
+        pg1_tx = self.statistics.get_counter('/interfaces/pg1/tx')
+        if_tx = self.statistics.get_counter('/if/tx')
+
+        self.assertEqual(pg1_tx[0]['bytes'],
+                         if_tx[0][self.pg1.sw_if_index]['bytes'])
+        for i in self.pg_interfaces:
+            i.unconfig()
+            i.admin_down()
+
+    def test_symlink_add_del_interfaces(self):
+        """Test symlinks when adding and deleting interfaces"""
+        # We first create and delete interfaces
+        self.create_loopback_interfaces(1)
+        self.create_pg_interfaces(range(1))
+        self.loop0.remove_vpp_config()
+        self.create_pg_interfaces(range(2))
+
+        for i in self.pg_interfaces:
+            i.admin_up()
+            i.config_ip4()
+            i.resolve_arp()
+
+        p = list()
+        bytes_to_send = 0
+        for i in range(5):
+            packet = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
+                      IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4))
+            bytes_to_send += len(packet)
+            p.append(packet)
+
+        tx_before_sending = self.statistics.get_counter('/interfaces/pg1/tx')
+        rx_before_sending = self.statistics.get_counter('/interfaces/pg0/rx')
+        self.send_and_expect(self.pg0, p, self.pg1)
+        tx = self.statistics.get_counter('/interfaces/pg1/tx')
+        rx = self.statistics.get_counter('/interfaces/pg0/rx')
+
+        # We wait for nodes symlinks to update (interfaces created/deleted).
+        # ... and packets to be sent
+        self.sleep(0.1)
+        vectors = self.statistics.get_counter('/nodes/pg1-tx/vectors')
+
+        self.assertEqual(tx[0]['bytes'] - tx_before_sending[0]['bytes'],
+                         bytes_to_send)
+        self.assertEqual(tx[0]['packets'] - tx_before_sending[0]['packets'],
+                         5)
+        self.assertEqual(rx[0]['bytes'] - rx_before_sending[0]['bytes'],
+                         bytes_to_send)
+        self.assertEqual(rx[0]['packets'] - rx_before_sending[0]['packets'],
+                         5)
+        self.assertEqual(vectors[0], rx[0]['packets'])
+
+        for i in self.pg_interfaces:
+            i.unconfig()
+            i.admin_down()
+
+    def test_index_consistency(self):
+        """Test index consistency despite changes in the stats"""
+        d = self.statistics.ls(['/if/names'])
+        self.create_loopback_interfaces(10)
+        for i in range(10):
+            try:
+                s = self.statistics.dump(d)
+                break
+            except:
+                pass
+        k, v = s.popitem()
+        self.assertEqual(len(v), 11)
+
+        for i in self.lo_interfaces:
+            i.remove_vpp_config()
+
+    @unittest.skip("Manual only")
+    def test_mem_leak(self):
+        def loop():
+            print('Running loop')
+            for i in range(50):
+                rv = self.vapi.papi.tap_create_v2(id=i, use_random_mac=1)
+                self.assertEqual(rv.retval, 0)
+                rv = self.vapi.papi.tap_delete_v2(sw_if_index=rv.sw_if_index)
+                self.assertEqual(rv.retval, 0)
+
+        before = self.statistics.get_counter('/mem/statseg/used')
+        loop()
+        self.vapi.cli("memory-trace on stats-segment")
+        for j in range(100):
+            loop()
+        print(self.vapi.cli("show memory stats-segment verbose"))
+        print('AFTER', before,
+              self.statistics.get_counter('/mem/statseg/used'))
+
+
 if __name__ == '__main__':
     unittest.main(testRunner=VppTestRunner)