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