Convert clear [run|interfaces] command to PAPI
[csit.git] / resources / libraries / python / VppCounters.py
1 # Copyright (c) 2016 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
5 #
6 #     http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 """VPP counters utilities library."""
15
16 import time
17
18 from robot.api import logger
19 from resources.libraries.python.PapiExecutor import PapiExecutor
20 from resources.libraries.python.topology import NodeType, Topology
21 from resources.libraries.python.VatExecutor import VatExecutor, VatTerminal
22
23
24 class VppCounters(object):
25     """VPP counters utilities."""
26
27     def __init__(self):
28         self._stats_table = None
29
30     @staticmethod
31     def vpp_show_errors(node):
32         """Run "show errors" debug CLI command.
33
34         :param node: Node to run command on.
35         :type node: dict
36         """
37         vat = VatExecutor()
38         vat.execute_script("show_errors.vat", node, json_out=False)
39         vat.script_should_have_passed()
40
41     @staticmethod
42     def vpp_show_errors_verbose(node):
43         """Run "show errors verbose" debug CLI command.
44
45         :param node: Node to run command on.
46         :type node: dict
47         """
48         vat = VatExecutor()
49         vat.execute_script("show_errors_verbose.vat", node, json_out=False)
50         vat.script_should_have_passed()
51
52     @staticmethod
53     def vpp_show_errors_on_all_duts(nodes, verbose=False):
54         """Show errors on all DUTs.
55
56         :param nodes: VPP nodes.
57         :param verbose: If True show verbose output.
58         :type nodes: dict
59         :type verbose: bool
60         """
61
62         for node in nodes.values():
63             if node['type'] == NodeType.DUT:
64                 if verbose:
65                     VppCounters.vpp_show_errors_verbose(node)
66                 else:
67                     VppCounters.vpp_show_errors(node)
68
69     @staticmethod
70     def vpp_show_runtime(node):
71         """Run "show runtime" CLI command.
72
73         :param node: Node to run command on.
74         :type node: dict
75         """
76         vat = VatExecutor()
77         vat.execute_script("show_runtime.vat", node, json_out=False)
78         vat.script_should_have_passed()
79
80     @staticmethod
81     def show_runtime_counters_on_all_duts(nodes):
82         """Clear VPP runtime counters on all DUTs.
83
84         :param nodes: VPP nodes.
85         :type nodes: dict
86         """
87         for node in nodes.values():
88             if node['type'] == NodeType.DUT:
89                 VppCounters.vpp_show_runtime(node)
90
91     @staticmethod
92     def vpp_show_runtime_verbose(node):
93         """Run "show runtime verbose" CLI command.
94
95         :param node: Node to run command on.
96         :type node: dict
97         """
98         vat = VatExecutor()
99         vat.execute_script("show_runtime_verbose.vat", node, json_out=False)
100         vat.script_should_have_passed()
101
102     @staticmethod
103     def vpp_show_hardware_detail(node):
104         """Run "show hardware-interfaces detail" debug CLI command.
105
106         :param node: Node to run command on.
107         :type node: dict
108         """
109         vat = VatExecutor()
110         vat.execute_script("show_hardware_detail.vat", node, json_out=False)
111         vat.script_should_have_passed()
112
113     @staticmethod
114     def vpp_clear_runtime(node):
115         """Run "clear runtime" CLI command.
116
117         :param node: Node to run command on.
118         :type node: dict
119         """
120         cmd = 'cli_inband'
121         cmd_reply = 'cli_inband_reply'
122         err_msg = "Failed to run '{cmd}' PAPI command on host {host}!".format(
123             host=node['host'], cmd=cmd)
124         args = dict(cmd='clear runtime')
125         with PapiExecutor(node) as papi_exec:
126             papi_resp = papi_exec.add(cmd, **args).execute_should_pass(err_msg)
127         data = papi_resp.reply[0]['api_reply'][cmd_reply]
128         if data['retval'] != 0:
129             raise RuntimeError("Failed to clear runtime on host {host}".
130                                format(host=node['host']))
131
132     @staticmethod
133     def clear_runtime_counters_on_all_duts(nodes):
134         """Run "clear runtime" CLI command on all DUTs.
135
136         :param nodes: VPP nodes.
137         :type nodes: dict
138         """
139         for node in nodes.values():
140             if node['type'] == NodeType.DUT:
141                 VppCounters.vpp_clear_runtime(node)
142
143     @staticmethod
144     def vpp_clear_interface_counters(node):
145         """Clear interface counters on VPP node.
146
147         :param node: Node to clear interface counters on.
148         :type node: dict
149         """
150         cmd = 'cli_inband'
151         cmd_reply = 'cli_inband_reply'
152         err_msg = "Failed to run '{cmd}' PAPI command on host {host}!".format(
153             host=node['host'], cmd=cmd)
154         args = dict(cmd='clear interfaces')
155         with PapiExecutor(node) as papi_exec:
156             papi_resp = papi_exec.add(cmd, **args).execute_should_pass(err_msg)
157         data = papi_resp.reply[0]['api_reply'][cmd_reply]
158         if data['retval'] != 0:
159             raise RuntimeError("Failed to clear interfaces on host {host}".
160                                format(host=node['host']))
161
162     @staticmethod
163     def clear_interface_counters_on_all_duts(nodes):
164         """Clear interface counters on all DUTs.
165
166         :param nodes: VPP nodes.
167         :type nodes: dict
168         """
169         for node in nodes.values():
170             if node['type'] == NodeType.DUT:
171                 VppCounters.vpp_clear_interface_counters(node)
172
173     @staticmethod
174     def vpp_clear_hardware_counters(node):
175         """Clear interface hardware counters on VPP node.
176
177         :param node: Node to clear hardware counters on.
178         :type node: dict
179         """
180         vat = VatExecutor()
181         vat.execute_script('clear_hardware.vat', node)
182         vat.script_should_have_passed()
183
184     @staticmethod
185     def clear_hardware_counters_on_all_duts(nodes):
186         """Clear hardware counters on all DUTs.
187
188         :param nodes: VPP nodes.
189         :type nodes: dict
190         """
191         for node in nodes.values():
192             if node['type'] == NodeType.DUT:
193                 VppCounters.vpp_clear_hardware_counters(node)
194
195     @staticmethod
196     def vpp_clear_errors_counters(node):
197         """Clear errors counters on VPP node.
198
199         :param node: Node to clear errors counters on.
200         :type node: dict
201         """
202         vat = VatExecutor()
203         vat.execute_script('clear_errors.vat', node)
204         vat.script_should_have_passed()
205
206     @staticmethod
207     def clear_error_counters_on_all_duts(nodes):
208         """Clear VPP errors counters on all DUTs.
209
210         :param nodes: VPP nodes.
211         :type nodes: dict
212         """
213         for node in nodes.values():
214             if node['type'] == NodeType.DUT:
215                 VppCounters.vpp_clear_errors_counters(node)
216
217     def vpp_dump_stats_table(self, node):
218         """Dump stats table on VPP node.
219
220         :param node: Node to dump stats table on.
221         :type node: dict
222         :returns: Stats table.
223         """
224         with VatTerminal(node) as vat:
225             vat.vat_terminal_exec_cmd('want_stats enable')
226             for _ in range(0, 12):
227                 stats_table = vat.vat_terminal_exec_cmd('dump_stats_table')
228                 if stats_table['interface_counters']:
229                     self._stats_table = stats_table
230                     return stats_table
231                 time.sleep(1)
232             return None
233
234     def vpp_get_ipv4_interface_counter(self, node, interface):
235         """
236
237         :param node: Node to get interface IPv4 counter on.
238         :param interface: Interface name.
239         :type node: dict
240         :type interface: str
241         :returns: Interface IPv4 counter.
242         :rtype: int
243         """
244         return self.vpp_get_ipv46_interface_counter(node, interface, False)
245
246     def vpp_get_ipv6_interface_counter(self, node, interface):
247         """
248
249         :param node: Node to get interface IPv6 counter on.
250         :param interface: Interface name.
251         :type node: dict
252         :type interface: str
253         :returns: Interface IPv6 counter.
254         :rtype: int
255         """
256         return self.vpp_get_ipv46_interface_counter(node, interface, True)
257
258     def vpp_get_ipv46_interface_counter(self, node, interface, is_ipv6=True):
259         """Return interface IPv4/IPv6 counter.
260
261         :param node: Node to get interface IPv4/IPv6 counter on.
262         :param interface: Interface name.
263         :param is_ipv6: Specify IP version.
264         :type node: dict
265         :type interface: str
266         :type is_ipv6: bool
267         :returns: Interface IPv4/IPv6 counter.
268         :rtype: int
269         """
270         version = 'ip6' if is_ipv6 else 'ip4'
271         topo = Topology()
272         if_index = topo.get_interface_sw_index(node, interface)
273         if if_index is None:
274             logger.trace('{i} sw_index not found.'.format(i=interface))
275             return 0
276
277         if_counters = self._stats_table.get('interface_counters')
278         if not if_counters:
279             logger.trace('No interface counters.')
280             return 0
281         for counter in if_counters:
282             if counter['vnet_counter_type'] == version:
283                 data = counter['data']
284                 return data[if_index]
285         logger.trace('{i} {v} counter not found.'.format(
286             i=interface, v=version))
287         return 0
288
289     @staticmethod
290     def show_vpp_statistics(node):
291         """Show [error, hardware, interface] stats.
292
293         :param node: VPP node.
294         :type node: dict
295         """
296         VppCounters.vpp_show_errors(node)
297         VppCounters.vpp_show_hardware_detail(node)
298         VppCounters.vpp_show_runtime(node)
299
300     @staticmethod
301     def show_statistics_on_all_duts(nodes, sleeptime=5):
302         """Show VPP statistics on all DUTs.
303
304         :param nodes: VPP nodes.
305         :type nodes: dict
306         :param sleeptime: Time to wait for traffic to arrive back to TG.
307         :type sleeptime: int
308         """
309         logger.trace('Waiting for statistics to be collected')
310         time.sleep(sleeptime)
311         for node in nodes.values():
312             if node['type'] == NodeType.DUT:
313                 VppCounters.show_vpp_statistics(node)