+
+ @staticmethod
+ def vpp_sw_interface_rx_placement_dump(node):
+ """Dump VPP interface RX placement on node.
+
+ :param node: Node to run command on.
+ :type node: dict
+ :returns: Thread mapping information as a list of dictionaries.
+ :rtype: list
+ """
+
+ cmd = 'sw_interface_rx_placement_dump'
+ cmd_reply = 'sw_interface_rx_placement_details'
+ err_msg = "Failed to run '{cmd}' PAPI command on host {host}!".format(
+ cmd=cmd, host=node['host'])
+ with PapiExecutor(node) as papi_exec:
+ for ifc in node['interfaces'].values():
+ if ifc['vpp_sw_index'] is not None:
+ papi_exec.add(cmd, sw_if_index=ifc['vpp_sw_index'])
+ papi_resp = papi_exec.get_dump(err_msg)
+ thr_mapping = [s[cmd_reply] for r in papi_resp.reply
+ for s in r['api_reply']]
+ return sorted(thr_mapping, key=lambda k: k['sw_if_index'])
+
+ @staticmethod
+ def vpp_sw_interface_set_rx_placement(node, sw_if_index, queue_id,
+ worker_id):
+ """Set interface RX placement to worker on node.
+
+ :param node: Node to run command on.
+ :param sw_if_index: VPP SW interface index.
+ :param queue_id: VPP interface queue ID.
+ :param worker_id: VPP worker ID (indexing from 0).
+ :type node: dict
+ :type sw_if_index: int
+ :type queue_id: int
+ :type worker_id: int
+ :raises RuntimeError: If failed to run command on host or if no API
+ reply received.
+ """
+
+ cmd = 'sw_interface_set_rx_placement'
+ cmd_reply = 'sw_interface_set_rx_placement_reply'
+ err_msg = "Failed to run '{cmd}' PAPI command on host {host}!".format(
+ host=node['host'], cmd=cmd)
+ args = dict(sw_if_index=sw_if_index, queue_id=queue_id,
+ worker_id=worker_id)
+ with PapiExecutor(node) as papi_exec:
+ papi_resp = papi_exec.add(cmd, **args).execute_should_pass(err_msg)
+ data = papi_resp.reply[0]['api_reply'][cmd_reply]
+ if data['retval'] != 0:
+ raise RuntimeError("Failed to set interface RX placement "
+ "to worker on host {host}".
+ format(host=node['host']))
+
+ @staticmethod
+ def vpp_round_robin_rx_placement(node, prefix):
+ """Set Round Robin interface RX placement on all worker threads
+ on node.
+
+ :param node: Topology nodes.
+ :param prefix: Interface name prefix.
+ :type node: dict
+ :type prefix: str
+ """
+ worker_id = 0
+ worker_cnt = len(VPPUtil.vpp_show_threads(node)) - 1
+ for placement in InterfaceUtil.vpp_sw_interface_rx_placement_dump(node):
+ for interface in node['interfaces'].values():
+ if placement['sw_if_index'] == interface['vpp_sw_index'] \
+ and prefix in interface['name']:
+ InterfaceUtil.vpp_sw_interface_set_rx_placement(
+ node, placement['sw_if_index'], placement['queue_id'],
+ worker_id % worker_cnt)
+ worker_id += 1
+
+ @staticmethod
+ def vpp_round_robin_rx_placement_on_all_duts(nodes, prefix):
+ """Set Round Robin interface RX placement on all worker threads
+ on all DUTs.
+
+ :param nodes: Topology nodes.
+ :param prefix: Interface name prefix.
+ :type nodes: dict
+ :type prefix: str
+ """
+ for node in nodes.values():
+ if node['type'] == NodeType.DUT:
+ InterfaceUtil.vpp_round_robin_rx_placement(node, prefix)