PapiExecutor always verifies
[csit.git] / resources / libraries / python / Memif.py
1 # Copyright (c) 2019 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 """Memif interface library."""
15
16
17 from enum import IntEnum
18 from robot.api import logger
19
20 from resources.libraries.python.topology import NodeType, Topology
21 from resources.libraries.python.PapiExecutor import PapiExecutor
22 from resources.libraries.python.L2Util import L2Util
23
24
25 class MemifRole(IntEnum):
26     """Memif interface roles"""
27     MASTER = 0
28     SLAVE = 1
29
30
31 class Memif(object):
32     """Memif interface class"""
33
34     def __init__(self):
35         pass
36
37     @staticmethod
38     def _memif_details(node):
39         """Get the memif dump details on the given node.
40
41         :param node: Given node to get Memif dump from.
42         :type node: dict
43         :returns: List of memif interfaces extracted from Papi response.
44         :rtype: list
45         """
46         with PapiExecutor(node) as papi_exec:
47             details = papi_exec.add("memif_dump").get_details()
48
49         for memif in details:
50             memif["if_name"] = memif["if_name"].rstrip('\x00')
51             memif["hw_addr"] = L2Util.bin_to_mac(memif["hw_addr"])
52
53         logger.debug("MEMIF details:\n{details}".format(details=details))
54
55         return details
56
57     @staticmethod
58     def _memif_socket_filename_add_del(node, is_add, filename, sid):
59         """Create Memif socket on the given node.
60
61         :param node: Given node to create Memif socket on.
62         :param is_add: If True, socket is added, otherwise deleted.
63         :param filename: Memif interface socket filename.
64         :param sid: Socket ID.
65         :type node: dict
66         :type is_add: bool
67         :type filename: str
68         :type sid: str
69         :returns: Verified data from PAPI response. In this case, the response
70             includes only retval.
71         :rtype: dict
72         """
73         cmd = 'memif_socket_filename_add_del'
74         err_msg = 'Failed to create memif socket on host {host}'.format(
75             host=node['host'])
76         args = dict(
77             is_add=int(is_add),
78             socket_id=int(sid),
79             socket_filename=str('/tmp/' + filename)
80         )
81         with PapiExecutor(node) as papi_exec:
82             return papi_exec.add(cmd, **args).get_reply(err_msg)
83
84     @staticmethod
85     def _memif_create(node, mid, sid, rxq=1, txq=1, role=1):
86         """Create Memif interface on the given node, return its sw_if_index.
87
88         :param node: Given node to create Memif interface on.
89         :param mid: Memif interface ID.
90         :param sid: Socket ID.
91         :param rxq: Number of RX queues; 0 means do not set.
92         :param txq: Number of TX queues; 0 means do not set.
93         :param role: Memif interface role [master=0|slave=1]. Default is slave.
94         :type node: dict
95         :type mid: str
96         :type sid: str
97         :type rxq: int
98         :type txq: int
99         :type role: int
100         :returns: sw_if_index
101         :rtype: int
102         """
103         cmd = 'memif_create'
104         err_msg = 'Failed to create memif interface on host {host}'.format(
105             host=node['host'])
106         args = dict(
107             role=role,
108             rx_queues=int(rxq),
109             tx_queues=int(txq),
110             socket_id=int(sid),
111             id=int(mid)
112         )
113         with PapiExecutor(node) as papi_exec:
114             return papi_exec.add(cmd, **args).get_sw_if_index(err_msg)
115
116     @staticmethod
117     def create_memif_interface(node, filename, mid, sid, rxq=1, txq=1,
118                                role="SLAVE"):
119         """Create Memif interface on the given node.
120
121         :param node: Given node to create Memif interface on.
122         :param filename: Memif interface socket filename.
123         :param mid: Memif interface ID.
124         :param sid: Socket ID.
125         :param rxq: Number of RX queues; 0 means do not set.
126         :param txq: Number of TX queues; 0 means do not set.
127         :param role: Memif interface role [master=0|slave=1]. Default is master.
128         :type node: dict
129         :type filename: str
130         :type mid: str
131         :type sid: str
132         :type rxq: int
133         :type txq: int
134         :type role: str
135         :returns: SW interface index.
136         :rtype: int
137         :raises ValueError: If command 'create memif' fails.
138         """
139
140         role = getattr(MemifRole, role.upper()).value
141
142         # Create socket
143         Memif._memif_socket_filename_add_del(node, True, filename, sid)
144
145         # Create memif
146         sw_if_index = Memif._memif_create(
147             node, mid, sid, rxq=rxq, txq=txq, role=role)
148
149         # Update Topology
150         if_key = Topology.add_new_port(node, 'memif')
151         Topology.update_interface_sw_if_index(node, if_key, sw_if_index)
152
153         ifc_name = Memif.vpp_get_memif_interface_name(node, sw_if_index)
154         Topology.update_interface_name(node, if_key, ifc_name)
155
156         ifc_mac = Memif.vpp_get_memif_interface_mac(node, sw_if_index)
157         Topology.update_interface_mac_address(node, if_key, ifc_mac)
158
159         Topology.update_interface_memif_socket(node, if_key, '/tmp/' + filename)
160         Topology.update_interface_memif_id(node, if_key, mid)
161         Topology.update_interface_memif_role(node, if_key, str(role))
162
163         return sw_if_index
164
165     @staticmethod
166     def show_memif(node):
167         """Show Memif data for the given node.
168
169         :param node: Given node to show Memif data on.
170         :type node: dict
171         """
172
173         Memif._memif_details(node)
174
175     @staticmethod
176     def show_memif_on_all_duts(nodes):
177         """Show Memif data on all DUTs.
178
179         :param nodes: Topology nodes.
180         :type nodes: dict
181         """
182         for node in nodes.values():
183             if node['type'] == NodeType.DUT:
184                 Memif.show_memif(node)
185
186     @staticmethod
187     def vpp_get_memif_interface_name(node, sw_if_index):
188         """Get Memif interface name from Memif interfaces dump.
189
190         :param node: DUT node.
191         :param sw_if_index: DUT node.
192         :type node: dict
193         :type sw_if_index: int
194         :returns: Memif interface name, or None if not found.
195         :rtype: str
196         """
197
198         details = Memif._memif_details(node)
199
200         for memif in details:
201             if memif["sw_if_index"] == sw_if_index:
202                 return memif["if_name"]
203         return None
204
205     @staticmethod
206     def vpp_get_memif_interface_mac(node, sw_if_index):
207         """Get Memif interface MAC address from Memif interfaces dump.
208
209         :param node: DUT node.
210         :param sw_if_index: DUT node.
211         :type node: dict
212         :type sw_if_index: int
213         :returns: Memif interface MAC address, or None if not found.
214         :rtype: str
215         """
216
217         details = Memif._memif_details(node)
218
219         for memif in details:
220             if memif["sw_if_index"] == sw_if_index:
221                 return memif["hw_addr"]
222         return None