stats: adding symlinks for nodes and interfaces in the stat segment
[vpp.git] / test / test_stats_client.py
1 #!/usr/bin/env python3
2
3 import unittest
4 import psutil
5 from vpp_papi.vpp_stats import VPPStats
6
7 from framework import tag_fixme_vpp_workers
8 from framework import VppTestCase, VppTestRunner
9 from scapy.layers.l2 import Ether
10 from scapy.layers.inet import IP
11
12
13 @tag_fixme_vpp_workers
14 class StatsClientTestCase(VppTestCase):
15     """Test Stats Client"""
16
17     @classmethod
18     def setUpClass(cls):
19         super(StatsClientTestCase, cls).setUpClass()
20
21     @classmethod
22     def tearDownClass(cls):
23         super(StatsClientTestCase, cls).tearDownClass()
24
25     @classmethod
26     def setUpConstants(cls):
27         cls.extra_vpp_statseg_config = "per-node-counters on"
28         cls.extra_vpp_statseg_config += "update-interval 0.05"
29         super(StatsClientTestCase, cls).setUpConstants()
30
31     def test_set_errors(self):
32         """Test set errors"""
33         self.assertEqual(self.statistics.set_errors(), {})
34         self.assertEqual(
35             self.statistics.get_counter('/err/ethernet-input/no error'), [0])
36
37     def test_client_fd_leak(self):
38         """Test file descriptor count - VPP-1486"""
39
40         cls = self.__class__
41         p = psutil.Process()
42         initial_fds = p.num_fds()
43
44         for _ in range(100):
45             stats = VPPStats(socketname=cls.get_stats_sock_path())
46             stats.disconnect()
47
48         ending_fds = p.num_fds()
49         self.assertEqual(initial_fds, ending_fds,
50                          "initial client side file descriptor count: %s "
51                          "is not equal to "
52                          "ending client side file descriptor count: %s" % (
53                              initial_fds, ending_fds))
54
55     def test_symlink_values(self):
56         """Test symlinks reported values"""
57         self.create_pg_interfaces(range(2))
58
59         for i in self.pg_interfaces:
60             i.admin_up()
61             i.config_ip4()
62             i.resolve_arp()
63
64         p = list()
65         for i in range(5):
66             packet = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
67                       IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4))
68             p.append(packet)
69
70         self.send_and_expect(self.pg0, p, self.pg1)
71
72         pg1_tx = self.statistics.get_counter('/interfaces/pg1/tx')
73         if_tx = self.statistics.get_counter('/if/tx')
74
75         self.assertEqual(pg1_tx[0]['bytes'],
76                          if_tx[0][self.pg1.sw_if_index]['bytes'])
77         for i in self.pg_interfaces:
78             i.unconfig()
79             i.admin_down()
80
81     def test_symlink_add_del_interfaces(self):
82         """Test symlinks when adding and deleting interfaces"""
83         # We first create and delete interfaces
84         self.create_loopback_interfaces(1)
85         self.create_pg_interfaces(range(1))
86         self.loop0.remove_vpp_config()
87         self.create_pg_interfaces(range(2))
88
89         for i in self.pg_interfaces:
90             i.admin_up()
91             i.config_ip4()
92             i.resolve_arp()
93
94         p = list()
95         bytes_to_send = 0
96         for i in range(5):
97             packet = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
98                       IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4))
99             bytes_to_send += len(packet)
100             p.append(packet)
101
102         tx_before_sending = self.statistics.get_counter('/interfaces/pg1/tx')
103         rx_before_sending = self.statistics.get_counter('/interfaces/pg0/rx')
104         self.send_and_expect(self.pg0, p, self.pg1)
105         tx = self.statistics.get_counter('/interfaces/pg1/tx')
106         rx = self.statistics.get_counter('/interfaces/pg0/rx')
107
108         # We wait for nodes symlinks to update (interfaces created/deleted).
109         # ... and packets to be sent
110         self.sleep(0.1)
111         vectors = self.statistics.get_counter('/nodes/pg1-tx/vectors')
112
113         self.assertEqual(tx[0]['bytes'] - tx_before_sending[0]['bytes'],
114                          bytes_to_send)
115         self.assertEqual(tx[0]['packets'] - tx_before_sending[0]['packets'],
116                          5)
117         self.assertEqual(rx[0]['bytes'] - rx_before_sending[0]['bytes'],
118                          bytes_to_send)
119         self.assertEqual(rx[0]['packets'] - rx_before_sending[0]['packets'],
120                          5)
121         self.assertEqual(vectors[0], rx[0]['packets'])
122
123         for i in self.pg_interfaces:
124             i.unconfig()
125             i.admin_down()
126
127     def test_index_consistency(self):
128         """Test index consistency despite changes in the stats"""
129         d = self.statistics.ls(['/if/names'])
130         self.create_loopback_interfaces(10)
131         for i in range(10):
132             try:
133                 s = self.statistics.dump(d)
134                 break
135             except:
136                 pass
137         k, v = s.popitem()
138         self.assertEqual(len(v), 11)
139
140         for i in self.lo_interfaces:
141             i.remove_vpp_config()
142
143     @unittest.skip("Manual only")
144     def test_mem_leak(self):
145         def loop():
146             print('Running loop')
147             for i in range(50):
148                 rv = self.vapi.papi.tap_create_v2(id=i, use_random_mac=1)
149                 self.assertEqual(rv.retval, 0)
150                 rv = self.vapi.papi.tap_delete_v2(sw_if_index=rv.sw_if_index)
151                 self.assertEqual(rv.retval, 0)
152
153         before = self.statistics.get_counter('/mem/statseg/used')
154         loop()
155         self.vapi.cli("memory-trace on stats-segment")
156         for j in range(100):
157             loop()
158         print(self.vapi.cli("show memory stats-segment verbose"))
159         print('AFTER', before,
160               self.statistics.get_counter('/mem/statseg/used'))
161
162
163 if __name__ == '__main__':
164     unittest.main(testRunner=VppTestRunner)