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