-# Copyright (c) 2020 Cisco and/or its affiliates.
+# Copyright (c) 2021 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
from robot.api import logger
from resources.libraries.python.Constants import Constants
+from resources.libraries.python.CpuUtils import CpuUtils
from resources.libraries.python.DUTSetup import DUTSetup
from resources.libraries.python.IPAddress import IPAddress
from resources.libraries.python.L2Util import L2Util
:raises RuntimeError: If it is not possible to create loopback on the
node.
"""
- cmd = u"create_loopback"
+ cmd = u"create_loopback_instance"
args = dict(
- mac_address=L2Util.mac_to_bin(mac) if mac else 0
+ mac_address=L2Util.mac_to_bin(mac) if mac else 0,
+ is_specified=False,
+ user_instance=0,
)
err_msg = f"Failed to create loopback interface on host {node[u'host']}"
with PapiSocketExecutor(node) as papi_exec:
node, u"set logging class rdma level debug"
)
- cmd = u"rdma_create"
+ cmd = u"rdma_create_v2"
pci_addr = Topology.get_interface_pci_addr(node, if_key)
args = dict(
name=InterfaceUtil.pci_to_eth(node, pci_addr),
rxq_size=rxq_size,
txq_size=txq_size,
mode=getattr(RdmaMode, f"RDMA_API_MODE_{mode.upper()}").value,
+ # TODO: Set True for non-jumbo packets.
+ no_multi_seg=False,
+ max_pktlen=0,
)
err_msg = f"Failed to create RDMA interface on host {node[u'host']}"
with PapiSocketExecutor(node) as papi_exec:
details = papi_exec.get_details(err_msg)
return sorted(details, key=lambda k: k[u"sw_if_index"])
+ @staticmethod
+ def vpp_sw_interface_rx_placement_dump_on_all_duts(nodes):
+ """Dump VPP interface RX placement on all given nodes.
+
+ :param nodes: Nodes to run command on.
+ :type nodes: dict
+ :returns: Thread mapping information as a list of dictionaries.
+ :rtype: list
+ """
+ for node in nodes.values():
+ if node[u"type"] == NodeType.DUT:
+ InterfaceUtil.vpp_sw_interface_rx_placement_dump(node)
+
@staticmethod
def vpp_sw_interface_set_rx_placement(
node, sw_if_index, queue_id, worker_id):
papi_exec.add(cmd, **args).get_reply(err_msg)
@staticmethod
- def vpp_round_robin_rx_placement(node, prefix):
+ def vpp_round_robin_rx_placement(
+ node, prefix, dp_worker_limit=None
+ ):
"""Set Round Robin interface RX placement on all worker threads
on node.
+ If specified, dp_core_limit limits the number of physical cores used
+ for data plane I/O work. Other cores are presumed to do something else,
+ e.g. asynchronous crypto processing.
+ None means all workers are used for data plane work.
+ Note this keyword specifies workers, not cores.
+
:param node: Topology nodes.
:param prefix: Interface name prefix.
+ :param dp_worker_limit: How many cores for data plane work.
:type node: dict
:type prefix: str
+ :type dp_worker_limit: Optional[int]
"""
worker_id = 0
worker_cnt = len(VPPUtil.vpp_show_threads(node)) - 1
+ if dp_worker_limit is not None:
+ worker_cnt = min(worker_cnt, dp_worker_limit)
if not worker_cnt:
return
for placement in InterfaceUtil.vpp_sw_interface_rx_placement_dump(node):
worker_id += 1
@staticmethod
- def vpp_round_robin_rx_placement_on_all_duts(nodes, prefix):
+ def vpp_round_robin_rx_placement_on_all_duts(
+ nodes, prefix, dp_core_limit=None
+ ):
"""Set Round Robin interface RX placement on all worker threads
on all DUTs.
+ If specified, dp_core_limit limits the number of physical cores used
+ for data plane I/O work. Other cores are presumed to do something else,
+ e.g. asynchronous crypto processing.
+ None means all cores are used for data plane work.
+ Note this keyword specifies cores, not workers.
+
:param nodes: Topology nodes.
:param prefix: Interface name prefix.
+ :param dp_worker_limit: How many cores for data plane work.
:type nodes: dict
:type prefix: str
+ :type dp_worker_limit: Optional[int]
"""
for node in nodes.values():
if node[u"type"] == NodeType.DUT:
- InterfaceUtil.vpp_round_robin_rx_placement(node, prefix)
+ dp_worker_limit = CpuUtils.worker_count_from_cores_and_smt(
+ phy_cores=dp_core_limit,
+ smt_used=CpuUtils.is_smt_enabled(node[u"cpuinfo"]),
+ )
+ InterfaceUtil.vpp_round_robin_rx_placement(
+ node, prefix, dp_worker_limit
+ )