1 # Copyright (c) 2020 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 """Vhost-user interfaces library."""
16 from enum import IntEnum
18 from robot.api import logger
20 from resources.libraries.python.PapiExecutor import PapiSocketExecutor
21 from resources.libraries.python.topology import NodeType, Topology
22 from resources.libraries.python.InterfaceUtil import InterfaceUtil
25 class VirtioFeaturesFlags(IntEnum):
26 """Virtio Features Flags."""
27 VIRTIO_NET_F_API_CSUM = 0
28 VIRTIO_NET_F_API_GUEST_CSUM = 1
29 VIRTIO_NET_F_API_GSO = 6
30 VIRTIO_NET_F_API_GUEST_TSO4 = 7
31 VIRTIO_NET_F_API_GUEST_TSO6 = 8
32 VIRTIO_NET_F_API_GUEST_UFO = 10
33 VIRTIO_NET_F_API_HOST_TSO4 = 11
34 VIRTIO_NET_F_API_HOST_TSO6 = 12
35 VIRTIO_NET_F_API_HOST_UFO = 14
36 VIRTIO_NET_F_API_MRG_RXBUF = 15
37 VIRTIO_NET_F_API_CTRL_VQ = 17
38 VIRTIO_NET_F_API_GUEST_ANNOUNCE = 21
39 VIRTIO_NET_F_API_MQ = 22
40 VIRTIO_F_API_ANY_LAYOUT = 27
41 VIRTIO_F_API_INDIRECT_DESC = 28
45 """Vhost-user interfaces L1 library."""
48 def vpp_create_vhost_user_interface(
49 node, socket, is_server=False, virtio_feature_mask=None):
50 """Create Vhost-user interface on VPP node.
52 :param node: Node to create Vhost-user interface on.
53 :param socket: Vhost-user interface socket path.
54 :param is_server: Server side of connection. Default: False
55 :param virtio_feature_mask: Mask of virtio features to be enabled.
59 :type virtio_feature_mask: int
60 :returns: SW interface index.
63 cmd = u"create_vhost_user_if"
64 err_msg = f"Failed to create Vhost-user interface " \
65 f"on host {node[u'host']}"
66 if virtio_feature_mask is None:
69 enable_gso = VirtioFeatureMask.is_feature_enabled(
70 virtio_feature_mask, VirtioFeaturesFlags.VIRTIO_NET_F_API_GSO
73 is_server=bool(is_server),
74 sock_filename=str(socket),
75 enable_gso=bool(enable_gso)
78 with PapiSocketExecutor(node) as papi_exec:
79 sw_if_index = papi_exec.add(cmd, **args).get_sw_if_index(err_msg)
81 # Update the Topology:
82 if_key = Topology.add_new_port(node, u"vhost")
83 Topology.update_interface_sw_if_index(node, if_key, sw_if_index)
85 ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_if_index)
86 Topology.update_interface_name(node, if_key, ifc_name)
88 ifc_mac = InterfaceUtil.vpp_get_interface_mac(node, sw_if_index)
89 Topology.update_interface_mac_address(node, if_key, ifc_mac)
91 Topology.update_interface_vhost_socket(node, if_key, socket)
96 def get_vhost_user_if_name_by_sock(node, socket):
97 """Get Vhost-user interface name by socket.
99 :param node: Node to get Vhost-user interface name on.
100 :param socket: Vhost-user interface socket path.
103 :returns: Interface name or None if not found.
106 for interface in node[u"interfaces"].values():
107 if interface.get(u"socket") == socket:
108 return interface.get(u"name")
112 def get_vhost_user_mac_by_sw_index(node, sw_if_index):
113 """Get Vhost-user l2_address for the given interface from actual
116 :param node: VPP node to get interface data from.
117 :param sw_if_index: SW index of the specific interface.
119 :type sw_if_index: str
120 :returns: l2_address of the given interface.
123 return InterfaceUtil.vpp_get_interface_mac(node, sw_if_index)
126 def show_vpp_vhost_on_all_duts(nodes):
127 """Show Vhost-user on all DUTs.
129 :param nodes: VPP nodes.
132 for node in nodes.values():
133 if node[u"type"] == NodeType.DUT:
134 VhostUser.vhost_user_dump(node)
137 def vhost_user_dump(node):
138 """Get vhost-user data for the given node.
140 :param node: VPP node to get interface data from.
142 :returns: List of dictionaries with all vhost-user interfaces.
145 cmd = u"sw_interface_vhost_user_dump"
146 err_msg = f"Failed to get vhost-user dump on host {node['host']}"
148 with PapiSocketExecutor(node) as papi_exec:
149 details = papi_exec.add(cmd).get_details(err_msg)
151 logger.debug(f"Vhost-user details:\n{details}")
155 class VirtioFeatureMask:
156 """Virtio features utilities"""
159 def create_virtio_feature_mask(**kwargs):
160 """Create virtio feature mask with feature bits set according to kwargs.
161 :param kwargs: Key-value pairs of feature names and it's state
164 virtio_feature_mask = 0
166 if u"all" in kwargs and kwargs[u"all"] is True:
167 for virtio_feature_flag in VirtioFeaturesFlags:
168 virtio_feature_mask |= 1 << virtio_feature_flag.value
170 for feature_name, enabled in kwargs.items():
171 virtio_feature_name = \
172 u"VIRTIO_NET_F_API_" + feature_name.upper()
173 if virtio_feature_name not in VirtioFeaturesFlags.__members__:
174 raise ValueError(u"Unsupported virtio feature flag name")
176 virtio_feature_mask |= \
177 1 << VirtioFeaturesFlags[virtio_feature_name].value
179 return virtio_feature_mask
182 def is_feature_enabled(virtio_feature_mask, virtio_feature_flag):
183 """Checks if concrete virtio feature is enabled within
185 :param virtio_feature_mask: Mask of enabled virtio features
186 :param virtio_feature_flag: Checked virtio feature
187 :type virtio_feature_mask: int
188 :type virtio_feature_flag: VirtioFeaturesFlags
190 feature_flag_bit = 1 << virtio_feature_flag.value
191 return (virtio_feature_mask & feature_flag_bit) > 0