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