1 # Copyright (c) 2023 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:
6 # http://www.apache.org/licenses/LICENSE-2.0
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.
14 """Memif interface library."""
17 from enum import IntEnum
19 from robot.api import logger
21 from resources.libraries.python.topology import NodeType, Topology
22 from resources.libraries.python.PapiExecutor import PapiSocketExecutor
25 class MemifRole(IntEnum):
26 """Memif interface roles"""
32 """Memif interface class"""
38 def _memif_details(node):
39 """Get the memif dump details on the given node.
41 :param node: Given node to get Memif dump from.
43 :returns: List of memif interfaces extracted from Papi response.
47 with PapiSocketExecutor(node) as papi_exec:
48 details = papi_exec.add(cmd).get_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"])
57 logger.debug(f"MEMIF details:\n{details}")
62 def _memif_socket_filename_add_del(node, is_add, filename, sid):
63 """Create Memif socket on the given node.
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.
73 :returns: Verified data from PAPI response. In this case, the response
77 cmd = u"memif_socket_filename_add_del_v2"
78 err_msg = f"Failed to create memif socket on host {node[u'host']}"
82 socket_filename=str(u"/tmp/" + filename)
84 with PapiSocketExecutor(node) as papi_exec:
85 return papi_exec.add(cmd, **args).get_reply(err_msg)
88 def _memif_create(node, mid, sid, rxq=1, txq=1, role=1, use_dma=False):
89 """Create Memif interface on the given node, return its sw_if_index.
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 :param use_dma: Use DMA acceleration. Requires hardware support.
105 :returns: sw_if_index
108 cmd = u"memif_create_v2"
109 err_msg = f"Failed to create memif interface on host {node[u'host']}"
120 with PapiSocketExecutor(node) as papi_exec:
121 return papi_exec.add(cmd, **args).get_sw_if_index(err_msg)
124 def create_memif_interface(
125 node, filename, mid, sid, rxq=1, txq=1, role=u"SLAVE", use_dma=False
127 """Create Memif interface on the given node.
129 :param node: Given node to create Memif interface on.
130 :param filename: Memif interface socket filename.
131 :param mid: Memif interface ID.
132 :param sid: Socket ID.
133 :param rxq: Number of RX queues; 0 means do not set.
134 :param txq: Number of TX queues; 0 means do not set.
135 :param role: Memif interface role [master=0|slave=1]. Default is master.
136 :param use_dma: Use DMA acceleration. Requires hardware support.
145 :returns: SW interface index.
147 :raises ValueError: If command 'create memif' fails.
149 role = getattr(MemifRole, role.upper()).value
152 Memif._memif_socket_filename_add_del(node, True, filename, sid)
155 sw_if_index = Memif._memif_create(
156 node, mid, sid, rxq=rxq, txq=txq, role=role, use_dma=use_dma
160 if_key = Topology.add_new_port(node, u"memif")
161 Topology.update_interface_sw_if_index(node, if_key, sw_if_index)
163 ifc_name = Memif.vpp_get_memif_interface_name(node, sw_if_index)
164 Topology.update_interface_name(node, if_key, ifc_name)
166 ifc_mac = Memif.vpp_get_memif_interface_mac(node, sw_if_index)
167 Topology.update_interface_mac_address(node, if_key, ifc_mac)
169 Topology.update_interface_memif_socket(
170 node, if_key, u"/tmp/" + filename
172 Topology.update_interface_memif_id(node, if_key, mid)
173 Topology.update_interface_memif_role(node, if_key, str(role))
178 def show_memif(node):
179 """Show Memif data for the given node.
181 :param node: Given node to show Memif data on.
184 Memif._memif_details(node)
187 def show_memif_on_all_duts(nodes):
188 """Show Memif data on all DUTs.
190 :param nodes: Topology nodes.
193 for node in nodes.values():
194 if node[u"type"] == NodeType.DUT:
195 Memif.show_memif(node)
198 def vpp_get_memif_interface_name(node, sw_if_index):
199 """Get Memif interface name from Memif interfaces dump.
201 :param node: DUT node.
202 :param sw_if_index: DUT node.
204 :type sw_if_index: int
205 :returns: Memif interface name, or None if not found.
208 details = Memif._memif_details(node)
210 for memif in details:
211 if memif[u"sw_if_index"] == sw_if_index:
212 return memif[u"if_name"]
216 def vpp_get_memif_interface_mac(node, sw_if_index):
217 """Get Memif interface MAC address from Memif interfaces dump.
219 :param node: DUT node.
220 :param sw_if_index: DUT node.
222 :type sw_if_index: int
223 :returns: Memif interface MAC address, or None if not found.
226 details = Memif._memif_details(node)
228 for memif in details:
229 if memif[u"sw_if_index"] == sw_if_index:
230 return memif[u"hw_addr"]