aboutsummaryrefslogtreecommitdiffstats
path: root/resources/libraries
diff options
context:
space:
mode:
Diffstat (limited to 'resources/libraries')
-rw-r--r--resources/libraries/python/Constants.py18
-rw-r--r--resources/libraries/python/CpuUtils.py169
-rw-r--r--resources/libraries/python/QemuManager.py62
-rw-r--r--resources/libraries/python/autogen/Regenerator.py2
-rw-r--r--resources/libraries/robot/performance/performance_configuration.robot25
-rw-r--r--resources/libraries/robot/performance/performance_utils.robot53
-rw-r--r--resources/libraries/robot/shared/container.robot14
-rw-r--r--resources/libraries/robot/shared/default.robot8
8 files changed, 171 insertions, 180 deletions
diff --git a/resources/libraries/python/Constants.py b/resources/libraries/python/Constants.py
index 71673aff86..0f0003a763 100644
--- a/resources/libraries/python/Constants.py
+++ b/resources/libraries/python/Constants.py
@@ -34,12 +34,24 @@ class Constants(object):
# vat templates location
RESOURCES_TPL_VAT = 'resources/templates/vat'
+ # Kubernetes templates location
+ RESOURCES_TPL_K8S = 'resources/templates/kubernetes'
+
+ # KernelVM templates location
+ RESOURCES_TPL_VM = 'resources/templates/vm'
+
# OpenVPP VAT binary name
VAT_BIN_NAME = 'vpp_api_test'
# VPP service unit name
VPP_UNIT = 'vpp'
+ # Number of system CPU cores.
+ CPU_CNT_SYSTEM = 1
+
+ # Number of vswitch main thread CPU cores.
+ CPU_CNT_MAIN = 1
+
# QEMU binary path
QEMU_BIN_PATH = '/usr/bin'
@@ -58,12 +70,6 @@ class Constants(object):
# TRex install directory
TREX_INSTALL_DIR = '/opt/trex-core-2.35'
- # Kubernetes templates location
- RESOURCES_TPL_K8S = 'resources/templates/kubernetes'
-
- # KernelVM templates location
- RESOURCES_TPL_VM = 'resources/templates/vm'
-
# Honeycomb directory location at topology nodes:
REMOTE_HC_DIR = '/opt/honeycomb'
diff --git a/resources/libraries/python/CpuUtils.py b/resources/libraries/python/CpuUtils.py
index 57bf7fdb71..67bf312f5d 100644
--- a/resources/libraries/python/CpuUtils.py
+++ b/resources/libraries/python/CpuUtils.py
@@ -13,7 +13,11 @@
"""CPU utilities library."""
-from resources.libraries.python.ssh import SSH
+from robot.libraries.BuiltIn import BuiltIn
+
+from resources.libraries.python.Constants import Constants
+from resources.libraries.python.ssh import exec_cmd_no_error
+from resources.libraries.python.topology import Topology
__all__ = ["CpuUtils"]
@@ -66,19 +70,8 @@ class CpuUtils(object):
:type nodes: dict
:raises RuntimeError: If the ssh command "lscpu -p" fails.
"""
- ssh = SSH()
for node in nodes.values():
- ssh.connect(node)
- cmd = "lscpu -p"
- ret, stdout, stderr = ssh.exec_command(cmd)
-# parsing of "lscpu -p" output:
-# # CPU,Core,Socket,Node,,L1d,L1i,L2,L3
-# 0,0,0,0,,0,0,0,0
-# 1,1,0,0,,1,1,1,0
- if ret != 0:
- raise RuntimeError(
- "Failed to execute ssh command, ret: {} err: {}".format(
- ret, stderr))
+ stdout, _ = exec_cmd_no_error(node, 'lscpu -p')
node['cpuinfo'] = list()
for line in stdout.split("\n"):
if line and line[0] != "#":
@@ -243,58 +236,134 @@ class CpuUtils(object):
return cpu_range
@staticmethod
- def cpu_slice_of_list_for_nf(**kwargs):
- """Return list of node related list of CPU numbers.
+ def cpu_slice_of_list_for_nf(node, cpu_node, nf_chains=1, nf_nodes=1,
+ nf_chain=1, nf_node=1, nf_dtc=1, nf_mtcr=2,
+ nf_dtcr=1, skip_cnt=0):
+ """Return list of DUT node related list of CPU numbers. The main
+ computing unit is physical core count.
- :param kwargs: Key-value pairs used to compute placement.
- :type kwargs: dict
- :returns: Cpu numbers related to numa from argument.
+ :param node: DUT node.
+ :param cpu_node: Numa node number.
+ :param nf_chains: Number of NF chains.
+ :param nf_nodes: Number of NF nodes in chain.
+ :param nf_chain: Chain number indexed from 1.
+ :param nf_node: Node number indexed from 1.
+ :param vs_dtc: Amount of physical cores for vswitch dataplane.
+ :param nf_dtc: Amount of physical cores for NF dataplane.
+ :param nf_mtcr: NF main thread per core ratio.
+ :param nf_dtcr: NF dataplane thread per core ratio.
+ :param skip_cnt: Skip first "skip_cnt" CPUs.
+ :type node: dict
+ :param cpu_node: int.
+ :type nf_chains: int
+ :type nf_nodes: int
+ :type nf_chain: int
+ :type nf_node: int
+ :type vs_dtc: int
+ :type nf_dtc: int or float
+ :type nf_mtcr: int
+ :type nf_dtcr: int
+ :type skip_cnt: int
+ :returns: List of CPUs allocated to NF.
:rtype: list
:raises RuntimeError: If we require more cpus than available or if
placement is not possible due to wrong parameters.
"""
- if kwargs['chain_id'] - 1 >= kwargs['chains']:
+ if nf_chain - 1 >= nf_chains:
raise RuntimeError("ChainID is higher than total number of chains!")
- if kwargs['node_id'] - 1 >= kwargs['nodeness']:
- raise RuntimeError("NodeID is higher than chain nodeness!")
+ if nf_node - 1 >= nf_nodes:
+ raise RuntimeError("NodeID is higher than chain nodes!")
- smt_used = CpuUtils.is_smt_enabled(kwargs['node']['cpuinfo'])
- cpu_list = CpuUtils.cpu_list_per_node(kwargs['node'],
- kwargs['cpu_node'], smt_used)
- cpu_list_len = len(cpu_list)
-
- mt_req = ((kwargs['chains'] * kwargs['nodeness']) + kwargs['mtcr'] - 1)\
- / kwargs['mtcr']
- dt_req = ((kwargs['chains'] * kwargs['nodeness']) + kwargs['dtcr'] - 1)\
- / kwargs['dtcr']
-
- cpu_req = kwargs['skip_cnt'] + mt_req + dt_req
- if smt_used and cpu_req > cpu_list_len / CpuUtils.NR_OF_THREADS:
+ smt_used = CpuUtils.is_smt_enabled(node['cpuinfo'])
+ cpu_list = CpuUtils.cpu_list_per_node(node, cpu_node, smt_used)
+ # CPU thread sibling offset.
+ sib = len(cpu_list) / CpuUtils.NR_OF_THREADS
+
+ if not smt_used and not isinstance(nf_dtc, int):
+ raise RuntimeError("Cannot allocate if SMT is not enabled!")
+ # TODO: Workaround as we are using physical core as main unit, we must
+ # adjust number of physical dataplane cores in case of float for further
+ # array referencing. As rounding method in Py2.7 and Py3.x differs, we
+ # are using static mapping. This can be rewritten using flat arrays and
+ # different logic (from Physical core unit to Logical core unit).
+ dtc = 1 if not isinstance(nf_dtc, int) else nf_dtc
+
+ mt_req = ((nf_chains * nf_nodes) + nf_mtcr - 1) / nf_mtcr
+ dt_req = ((nf_chains * nf_nodes) + nf_dtcr - 1) / nf_dtcr
+ cpu_req = skip_cnt + mt_req + dt_req
+
+ if smt_used and cpu_req > len(cpu_list) / CpuUtils.NR_OF_THREADS:
raise RuntimeError("Not enough CPU cores available for placement!")
- elif not smt_used and cpu_req > cpu_list_len:
+ elif not smt_used and cpu_req > len(cpu_list):
raise RuntimeError("Not enough CPU cores available for placement!")
- offset = (kwargs['node_id'] - 1) + (kwargs['chain_id'] - 1)\
- * kwargs['nodeness']
- dtc = kwargs['dtc']
+ offset = (nf_node - 1) + (nf_chain - 1) * nf_nodes
try:
mt_odd = (offset / mt_req) & 1
- mt_skip = kwargs['skip_cnt'] + (offset % mt_req)
- dt_skip = kwargs['skip_cnt'] + mt_req + (offset % dt_req) * dtc
+ mt_skip = skip_cnt + (offset % mt_req)
+ dt_odd = (offset / dt_req) & 1
+ dt_skip = skip_cnt + mt_req + (offset % dt_req) * dtc
except ZeroDivisionError:
raise RuntimeError("Invalid placement combination!")
-
if smt_used:
- cpu_list_0 = cpu_list[:cpu_list_len / CpuUtils.NR_OF_THREADS]
- cpu_list_1 = cpu_list[cpu_list_len / CpuUtils.NR_OF_THREADS:]
+ mt_list = [cpu for cpu in cpu_list[mt_skip+sib:mt_skip+sib + 1]] \
+ if mt_odd else [cpu for cpu in cpu_list[mt_skip:mt_skip + 1]]
+ dt_list = [cpu for cpu in cpu_list[dt_skip+sib:dt_skip+sib + dtc]] \
+ if dt_odd else [cpu for cpu in cpu_list[dt_skip:dt_skip + dtc]]
+ if isinstance(nf_dtc, int):
+ dt_list = \
+ [cpu for cpu in cpu_list[dt_skip:dt_skip + dtc]]
+ dt_list += \
+ [cpu for cpu in cpu_list[dt_skip+sib:dt_skip+sib + dtc]]
+ else:
+ mt_list = [cpu for cpu in cpu_list[mt_skip:mt_skip + 1]]
+ dt_list = [cpu for cpu in cpu_list[dt_skip:dt_skip + dtc]]
- mt_cpu_list = [cpu for cpu in cpu_list_1[mt_skip:mt_skip + 1]] \
- if mt_odd else [cpu for cpu in cpu_list_0[mt_skip:mt_skip + 1]]
+ return mt_list + dt_list
- dt_cpu_list = [cpu for cpu in cpu_list_0[dt_skip:dt_skip + dtc]]
- dt_cpu_list += [cpu for cpu in cpu_list_1[dt_skip:dt_skip + dtc]]
- else:
- mt_cpu_list = [cpu for cpu in cpu_list[mt_skip:mt_skip + 1]]
- dt_cpu_list = [cpu for cpu in cpu_list[dt_skip:dt_skip + dtc]]
+ @staticmethod
+ def get_affinity_nf(nodes, node, nf_chains=1, nf_nodes=1, nf_chain=1,
+ nf_node=1, vs_dtc=1, nf_dtc=1, nf_mtcr=2, nf_dtcr=1):
+
+ """Get affinity of NF (network function). Result will be used to compute
+ the amount of CPUs and also affinity.
+
+ :param nodes: Physical topology nodes.
+ :param node: SUT node.
+ :param nf_chains: Number of NF chains.
+ :param nf_nodes: Number of NF nodes in chain.
+ :param nf_chain: Chain number indexed from 1.
+ :param nf_node: Node number indexed from 1.
+ :param vs_dtc: Amount of physical cores for vswitch dataplane.
+ :param nf_dtc: Amount of physical cores for NF dataplane.
+ :param nf_mtcr: NF main thread per core ratio.
+ :param nf_dtcr: NF dataplane thread per core ratio.
+ :type nodes: dict
+ :type node: dict
+ :type nf_chains: int
+ :type nf_nodes: int
+ :type nf_chain: int
+ :type nf_node: int
+ :type vs_dtc: int
+ :type nf_dtc: int or float
+ :type nf_mtcr: int
+ :type nf_dtcr: int
+ :returns: List of CPUs allocated to NF.
+ :rtype: list
+ """
+ skip_cnt = Constants.CPU_CNT_SYSTEM + Constants.CPU_CNT_MAIN + vs_dtc
+
+ interface_list = []
+ interface_list.append(
+ BuiltIn().get_variable_value('${{{node}_if1}}'.format(node=node)))
+ interface_list.append(
+ BuiltIn().get_variable_value('${{{node}_if2}}'.format(node=node)))
+
+ cpu_node = Topology.get_interfaces_numa_node(
+ nodes[node], *interface_list)
+
+ return CpuUtils.cpu_slice_of_list_for_nf(
+ node=nodes[node], cpu_node=cpu_node, nf_chains=nf_chains,
+ nf_nodes=nf_nodes, nf_chain=nf_chain, nf_node=nf_node,
+ nf_mtcr=nf_mtcr, nf_dtcr=nf_dtcr, nf_dtc=nf_dtc, skip_cnt=skip_cnt)
- return mt_cpu_list + dt_cpu_list
diff --git a/resources/libraries/python/QemuManager.py b/resources/libraries/python/QemuManager.py
index 0ea6164cb7..6f5db6ecbb 100644
--- a/resources/libraries/python/QemuManager.py
+++ b/resources/libraries/python/QemuManager.py
@@ -15,61 +15,14 @@
from collections import OrderedDict
-from robot.libraries.BuiltIn import BuiltIn
-
from resources.libraries.python.Constants import Constants
from resources.libraries.python.CpuUtils import CpuUtils
from resources.libraries.python.QemuUtils import QemuUtils
-from resources.libraries.python.topology import NodeType, Topology
+from resources.libraries.python.topology import NodeType
__all__ = ["QemuManager"]
-def get_affinity_vm(nodes, node, nf_chains=1, nf_nodes=1, nf_chain=1, nf_node=1,
- cpu_count_int=1, vnf_count_int=1):
- """Get affinity of VM. Result will be used to compute the amount of
- CPUs and also affinity.
-
- :param node: SUT nodes.
- :param node: DUT node.
- :param nf_chains: Number of NF chains.
- :param nf_nodes: Number of NF nodes in chain.
- :param nf_chain: Chain ID.
- :param nf_node: Node ID.
- :param cpu_count_int: Amount of Dataplane threads of vswitch.
- :param vnf_count_int: Amount of Dataplane threads of vnf.
- :type nodes: dict
- :type node: dict
- :type nf_chains: int
- :type nf_nodes: int
- :type nf_chain: int
- :type nf_node: int
- :type cpu_count_int: int
- :type vnf_count_int: int
- :returns: List of CPUs allocated to VM.
- :rtype: list
- """
- sut_sc = 1
- dut_mc = 1
- dut_dc = cpu_count_int
- skip_cnt = sut_sc + dut_mc + dut_dc
- dtc = vnf_count_int
-
- interface_list = []
- interface_list.append(
- BuiltIn().get_variable_value('${{{node}_if1}}'.format(node=node)))
- interface_list.append(
- BuiltIn().get_variable_value('${{{node}_if2}}'.format(node=node)))
-
- cpu_node = Topology.get_interfaces_numa_node(nodes[node], *interface_list)
-
- nf_cpus = CpuUtils.cpu_slice_of_list_for_nf(
- node=nodes[node], cpu_node=cpu_node, chains=nf_chains,
- nodeness=nf_nodes, chain_id=nf_chain, node_id=nf_node, mtcr=2, dtcr=1,
- dtc=dtc, skip_cnt=skip_cnt)
-
- return nf_cpus
-
class QemuManager(object):
"""QEMU lifecycle management class"""
@@ -97,8 +50,9 @@ class QemuManager(object):
nf_chains = int(kwargs['nf_chains'])
nf_nodes = int(kwargs['nf_nodes'])
queues = kwargs['rxq_count_int'] if kwargs['auto_scale'] else 1
- cpu_count_int = kwargs['cpu_count_int']
- vnf_count_int = kwargs['cpu_count_int'] if kwargs['auto_scale'] else 1
+ vs_dtc = kwargs['vs_dtc']
+ nf_dtc = kwargs['vs_dtc'] if kwargs['auto_scale'] else kwargs['nf_dtc']
+ nf_dtcr = kwargs['nf_dtcr'] if isinstance(kwargs['nf_dtcr'], int) else 2
img = Constants.QEMU_VM_KERNEL
@@ -113,10 +67,10 @@ class QemuManager(object):
vif2_mac = kwargs['tg_if2_mac'] if nf_node == nf_nodes \
else '52:54:00:00:{id:02x}:01'.format(id=qemu_id + 1)
- self.machines_affinity[name] = get_affinity_vm(
+ self.machines_affinity[name] = CpuUtils.get_affinity_nf(
nodes=self.nodes, node=node, nf_chains=nf_chains,
nf_nodes=nf_nodes, nf_chain=nf_chain, nf_node=nf_node,
- cpu_count_int=cpu_count_int, vnf_count_int=vnf_count_int)
+ vs_dtc=vs_dtc, nf_dtc=nf_dtc, nf_dtcr=nf_dtcr)
self.machines[name] = QemuUtils(
node=self.nodes[node], qemu_id=qemu_id,
@@ -131,10 +85,10 @@ class QemuManager(object):
jumbo_frames=kwargs['jumbo'])
self.machines[name].qemu_add_vhost_user_if(
sock1, jumbo_frames=kwargs['jumbo'], queues=queues,
- queue_size=1024)
+ queue_size=kwargs['perf_qemu_qsz'])
self.machines[name].qemu_add_vhost_user_if(
sock2, jumbo_frames=kwargs['jumbo'], queues=queues,
- queue_size=1024)
+ queue_size=kwargs['perf_qemu_qsz'])
def construct_vms_on_all_nodes(self, **kwargs):
"""Construct 1..Mx1..N VMs(s) with specified name on all nodes.
diff --git a/resources/libraries/python/autogen/Regenerator.py b/resources/libraries/python/autogen/Regenerator.py
index f47c88b022..85625c4c35 100644
--- a/resources/libraries/python/autogen/Regenerator.py
+++ b/resources/libraries/python/autogen/Regenerator.py
@@ -119,7 +119,7 @@ class Regenerator(object):
# Not supported by AVF driver.
# https://git.fd.io/vpp/tree/src/plugins/avf/README.md
emit = False
- if "-16vm-" in suite_id or "-16dcr-" in suite_id:
+ if "-16vm2t-" in suite_id or "-16dcr2t-" in suite_id:
if kwargs["phy_cores"] > 3:
# CSIT lab only has 28 (physical) core processors,
# so these test would fail when attempting to assign cores.
diff --git a/resources/libraries/robot/performance/performance_configuration.robot b/resources/libraries/robot/performance/performance_configuration.robot
index d9f5e3ab59..8a305e4409 100644
--- a/resources/libraries/robot/performance/performance_configuration.robot
+++ b/resources/libraries/robot/performance/performance_configuration.robot
@@ -64,7 +64,7 @@
| | | ... | Set Interface State | ${nodes['${dut}']} | ${${dut}_if2_1} | up
| | | Run Keyword Unless | '${if2_status}' == 'PASS'
| | | ... | Set Interface State | ${nodes['${dut}']} | ${${dut}_if2_2} | up
-| | All VPP Interfaces Ready Wait | ${nodes}
+| | All VPP Interfaces Ready Wait | ${nodes} | timeout=${600}
| | ${duts}= | Get Matches | ${nodes} | DUT*
| | :FOR | ${dut} | IN | @{duts}
| | | ${if1_status} | ${value}= | Run Keyword And Ignore Error
@@ -83,7 +83,7 @@
| | | ... | VPP Set Interface MTU | ${nodes['${dut}']} | ${${dut}_if2_1}
| | | Run Keyword Unless | '${if2_status}' == 'PASS'
| | | ... | VPP Set Interface MTU | ${nodes['${dut}']} | ${${dut}_if2_2}
-| | All VPP Interfaces Ready Wait | ${nodes}
+| | All VPP Interfaces Ready Wait | ${nodes} | timeout=${600}
| Set single interfaces in path up
| | [Documentation]
@@ -104,7 +104,7 @@
| | | ... | Set Interface State | ${nodes['${dut}']} | ${${dut}_if1_1} | up
| | | Run Keyword Unless | '${if1_status}' == 'PASS'
| | | ... | Set Interface State | ${nodes['${dut}']} | ${${dut}_if1_2} | up
-| | All VPP Interfaces Ready Wait | ${nodes}
+| | All VPP Interfaces Ready Wait | ${nodes} | timeout=${600}
| | ${duts}= | Get Matches | ${nodes} | DUT*
| | :FOR | ${dut} | IN | @{duts}
| | | ${if1_status} | ${value}= | Run Keyword And Ignore Error
@@ -2301,10 +2301,11 @@
| | ... | perf_qemu_qsz=${perf_qemu_qsz} | use_tuned_cfs=${use_tuned_cfs}
| | ... | auto_scale=${auto_scale} | vnf=${vnf}
| | ... | tg_if1_mac=${tg_if1_mac} | tg_if2_mac=${tg_if2_mac}
-| | ... | cpu_count_int=${cpu_count_int} | rxq_count_int=${rxq_count_int}
+| | ... | vs_dtc=${cpu_count_int} | nf_dtc=${nf_dtc} | nf_dtcr=${nf_dtcr}
+| | ... | rxq_count_int=${rxq_count_int}
| | Run Keyword | vnf_manager.Start All VMs | pinning=${True}
| | Run Keyword If | ${use_tuned_cfs} | vnf_manager.Set Scheduler All VMs
-| | All VPP Interfaces Ready Wait | ${nodes}
+| | All VPP Interfaces Ready Wait | ${nodes} | timeout=${600}
| | VPP round robin RX placement on all DUTs | ${nodes} | prefix=Virtual
| Configure guest VM with dpdk-testpmd connected via vhost-user
@@ -2392,9 +2393,10 @@
| | ... | ${perf_qemu_qsz}=${1024} | ${use_tuned_cfs}=${False}
| | ...
| | :FOR | ${number} | IN RANGE | 1 | ${vm_count}+1
-| | | ${nf_cpus}= | Create network function CPU list | ${dut}
-| | | ... | chains=${1} | nodeness=${vm_count} | chain_id=${1}
-| | | ... | node_id=${number} | auto_scale=${True}
+| | | ${nf_cpus}= | Get Affinity NF | ${nodes} | ${dut}
+| | | ... | nf_chains=${1} | nf_nodes=${vm_count}
+| | | ... | nf_chain=${1} | nf_node=${number}
+| | | ... | vs_dtc=${cpu_count_int} | nf_dtc=${cpu_count_int}
| | | ${sock1}= | Set Variable | /var/run/vpp/sock-${number}-1
| | | ${sock2}= | Set Variable | /var/run/vpp/sock-${number}-2
| | | ${vm}=
@@ -2528,9 +2530,10 @@
| | ... | ${perf_qemu_qsz}=${1024} | ${use_tuned_cfs}=${False}
| | ...
| | :FOR | ${number} | IN RANGE | 1 | ${vm_count}+1
-| | | ${nf_cpus}= | Create network function CPU list | ${dut}
-| | | ... | chains=${1} | nodeness=${vm_count} | chain_id=${1}
-| | | ... | node_id=${number} | auto_scale=${True}
+| | | ${nf_cpus}= | Get Affinity NF | ${nodes} | ${dut}
+| | | ... | nf_chains=${1} | nf_nodes=${vm_count}
+| | | ... | nf_chain=${1} | nf_node=${number}
+| | | ... | vs_dtc=${cpu_count_int} | nf_dtc=${cpu_count_int}
| | | ${sock1}= | Set Variable | /var/run/vpp/sock-${number}-1
| | | ${sock2}= | Set Variable | /var/run/vpp/sock-${number}-2
| | | ${vm}=
diff --git a/resources/libraries/robot/performance/performance_utils.robot b/resources/libraries/robot/performance/performance_utils.robot
index 45d8efe535..9661b522d8 100644
--- a/resources/libraries/robot/performance/performance_utils.robot
+++ b/resources/libraries/robot/performance/performance_utils.robot
@@ -406,56 +406,3 @@
| | Run Keyword If | ${dut_stats}==${True}
| | ... | Show runtime counters on all DUTs | ${nodes}
| | Stop traffic on tg
-
-| Create network function CPU list
-| | # TODO: Is there a better place for this keyword?
-| | # It is not exactly a performance utility.
-| | [Documentation]
-| | ... | Create list of CPUs allocated for network function base on SUT/DUT
-| | ... | placement and other network functions placement.
-| | ...
-| | ... | *Arguments:*
-| | ... | - dut - DUT node. Type: dictionary
-| | ... | - chains: Total number of chains. Type: integer
-| | ... | - nodeness: Total number of nodes per chain. Type: integer
-| | ... | - chain_id - Network function chain ID. Type: integer
-| | ... | - node_id - Network function node ID within chain. Type: integer
-| | ... | - mtcr - Main thread to core ratio. Type: integer
-| | ... | - dtcr - Dataplane thread to core ratio. Type: integer
-| | ... | - auto_scale - If True, use same amount of Dataplane threads for
-| | ... | network function as DUT, otherwise use single physical core for
-| | ... | every network function. Type: boolean
-| | ...
-| | ... | *Note:*
-| | ... | KW uses test variables \${cpu_count_int} set by
-| | ... | "Add worker threads and rxqueues to all DUTs"
-| | ...
-| | ... | *Example:*
-| | ...
-| | ... | \| Create network function CPU list \| ${nodes['DUT1']} \
-| | ... | \| 1 \| 1 \| 1 \| 1 \|
-| | ...
-| | [Arguments] | ${dut} | ${chains}=${1} | ${nodeness}=${1} | ${chain_id}=${1}
-| | ... | ${node_id}=${1} | ${mtcr}=${2} | ${dtcr}=${1} | ${auto_scale}=${False}
-| | ...
-| | ${sut_sc}= | Set Variable | ${1}
-| | ${dut_mc}= | Set Variable | ${1}
-| | ${dut_dc}= | Set Variable | ${cpu_count_int}
-| | ${skip}= | Evaluate | ${sut_sc} + ${dut_mc} + ${dut_dc}
-| | ${dtc}= | Set Variable If | ${auto_scale} | ${cpu_count_int} | ${1}
-| | ${if1_status} | ${value}= | Run Keyword And Ignore Error
-| | ... | Variable Should Exist | ${${dut}_if1}
-| | @{if_list}= | Run Keyword If | '${if1_status}' == 'PASS'
-| | ... | Create List | ${${dut}_if1}
-| | ... | ELSE | Create List | ${${dut}_if1_1} | ${${dut}_if1_2}
-| | ${if2_status} | ${value}= | Run Keyword And Ignore Error
-| | ... | Variable Should Exist | ${${dut}_if2}
-| | Run Keyword If | '${if2_status}' == 'PASS'
-| | ... | Append To List | ${if_list} | ${${dut}_if2}
-| | ... | ELSE | Append To List | ${if_list} | ${${dut}_if2_1} | ${${dut}_if2_2}
-| | ${dut_numa}= | Get interfaces numa node | ${nodes['${dut}']} | @{if_list}
-| | ${nf_cpus}= | Cpu slice of list for NF | node=${nodes['${dut}']}
-| | ... | cpu_node=${dut_numa} | chains=${chains} | nodeness=${nodeness}
-| | ... | chain_id=${chain_id} | node_id=${node_id} | mtcr=${mtcr}
-| | ... | dtcr=${dtcr} | dtc=${dtc} | skip_cnt=${skip}
-| | Return From Keyword | ${nf_cpus}
diff --git a/resources/libraries/robot/shared/container.robot b/resources/libraries/robot/shared/container.robot
index d1ec6d2a03..c1ab1af18d 100644
--- a/resources/libraries/robot/shared/container.robot
+++ b/resources/libraries/robot/shared/container.robot
@@ -41,6 +41,13 @@
| | [Arguments] | ${nf_chains}=${1} | ${nf_nodes}=${1} | ${nf_chain}=${1}
| | ... | ${nf_node}=${1} | ${auto_scale}=${True} | ${nested}=${False}
| | ...
+| | ${nf_dtcr_status} | ${value}= | Run Keyword And Ignore Error
+| | ... | Variable Should Exist | ${nf_dtcr}
+| | ${nf_dtcr}= | Run Keyword If | '${nf_dtcr_status}' == 'PASS'
+| | ... | Set Variable | ${nf_dtcr} | ELSE | Set Variable | ${1}
+| | ${nf_dtc}= | Run Keyword Unless | ${nested}
+| | ... | Set Variable If | ${auto_scale} | ${cpu_count_int}
+| | ... | ${nf_dtc}
| | ${duts}= | Get Matches | ${nodes} | DUT*
| | :FOR | ${dut} | IN | @{duts}
| | | ${nf_id}= | Evaluate | (${nf_chain} - ${1}) * ${nf_nodes} + ${nf_node}
@@ -56,9 +63,10 @@
| | | ... | ${root}/usr/share/vpp/:/usr/share/vpp/
| | | ${nf_cpus}= | Set Variable | ${None}
| | | ${nf_cpus}= | Run Keyword Unless | ${nested}
-| | | ... | Create network function CPU list | ${dut}
-| | | ... | chains=${nf_chains} | nodeness=${nf_nodes} | chain_id=${nf_chain}
-| | | ... | node_id=${nf_node} | auto_scale=${auto_scale}
+| | | ... | Get Affinity NF | ${nodes} | ${dut}
+| | | ... | nf_chains=${nf_chains} | nf_nodes=${nf_nodes}
+| | | ... | nf_chain=${nf_chain} | nf_node=${nf_node}
+| | | ... | vs_dtc=${cpu_count_int} | nf_dtc=${nf_dtc} | nf_dtcr=${nf_dtcr}
| | | &{cont_args}= | Create Dictionary
| | | ... | name=${dut}_${container_group}${nf_id}${uuid}
| | | ... | node=${nodes['${dut}']} | mnt=${mnt} | env=${env}
diff --git a/resources/libraries/robot/shared/default.robot b/resources/libraries/robot/shared/default.robot
index 569ff34812..6e26abc03b 100644
--- a/resources/libraries/robot/shared/default.robot
+++ b/resources/libraries/robot/shared/default.robot
@@ -14,6 +14,7 @@
*** Settings ***
| Variables | resources/libraries/python/topology.py
| Variables | resources/libraries/python/PapiHistory.py
+| Variables | resources/libraries/python/Constants.py
| ...
| Library | Collections
| Library | OperatingSystem
@@ -199,10 +200,13 @@
| | | ... | Append To List | ${if_list} | ${${dut}_if2_1} | ${${dut}_if2_2}
| | | ${numa}= | Get interfaces numa node | ${nodes['${dut}']} | @{if_list}
| | | ${smt_used}= | Is SMT enabled | ${nodes['${dut}']['cpuinfo']}
+| | | ${skip_cnt}= | Set variable | ${CPU_CNT_SYSTEM}
| | | ${cpu_main}= | Cpu list per node str | ${nodes['${dut}']} | ${numa}
-| | | ... | skip_cnt=${1} | cpu_cnt=${1}
+| | | ... | skip_cnt=${skip_cnt} | cpu_cnt=${CPU_CNT_MAIN}
+| | | ${skip_cnt}= | Evaluate | ${CPU_CNT_SYSTEM} + ${CPU_CNT_MAIN}
| | | ${cpu_wt}= | Cpu list per node str | ${nodes['${dut}']} | ${numa}
-| | | ... | skip_cnt=${2} | cpu_cnt=${cpu_count_int} | smt_used=${smt_used}
+| | | ... | skip_cnt=${skip_cnt} | cpu_cnt=${cpu_count_int}
+| | | ... | smt_used=${smt_used}
| | | ${thr_count_int}= | Run keyword if | ${smt_used}
| | | ... | Evaluate | int(${cpu_count_int}*2)
| | | ... | ELSE | Set variable | ${thr_count_int}