Code Review
/
csit.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
review
|
tree
raw
|
inline
| side by side
PAPI stats: Use single dump
[csit.git]
/
resources
/
libraries
/
python
/
InterfaceUtil.py
diff --git
a/resources/libraries/python/InterfaceUtil.py
b/resources/libraries/python/InterfaceUtil.py
index
1245a33
..
00a1933
100644
(file)
--- a/
resources/libraries/python/InterfaceUtil.py
+++ b/
resources/libraries/python/InterfaceUtil.py
@@
-1,4
+1,4
@@
-# Copyright (c) 202
0
Cisco and/or its affiliates.
+# Copyright (c) 202
1
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:
# 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:
@@
-20,6
+20,7
@@
from ipaddress import ip_address
from robot.api import logger
from resources.libraries.python.Constants import Constants
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
from resources.libraries.python.DUTSetup import DUTSetup
from resources.libraries.python.IPAddress import IPAddress
from resources.libraries.python.L2Util import L2Util
@@
-1029,9
+1030,11
@@
class InterfaceUtil:
:raises RuntimeError: If it is not possible to create loopback on the
node.
"""
:raises RuntimeError: If it is not possible to create loopback on the
node.
"""
- cmd = u"create_loopback"
+ cmd = u"create_loopback
_instance
"
args = dict(
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:
)
err_msg = f"Failed to create loopback interface on host {node[u'host']}"
with PapiSocketExecutor(node) as papi_exec:
@@
-1048,24
+1051,28
@@
class InterfaceUtil:
return sw_if_index
@staticmethod
return sw_if_index
@staticmethod
- def vpp_create_bond_interface(node, mode, load_balance=None, mac=None):
+ def vpp_create_bond_interface(
+ node, mode, load_balance=None, mac=None, gso=False):
"""Create bond interface on VPP node.
:param node: DUT node from topology.
:param mode: Link bonding mode.
:param load_balance: Load balance (optional, valid for xor and lacp
"""Create bond interface on VPP node.
:param node: DUT node from topology.
:param mode: Link bonding mode.
:param load_balance: Load balance (optional, valid for xor and lacp
- modes, otherwise ignored).
+ modes, otherwise ignored).
Default: None.
:param mac: MAC address to assign to the bond interface (optional).
:param mac: MAC address to assign to the bond interface (optional).
+ Default: None.
+ :param gso: Enable GSO support (optional). Default: False.
:type node: dict
:type mode: str
:type load_balance: str
:type mac: str
:type node: dict
:type mode: str
:type load_balance: str
:type mac: str
+ :type gso: bool
:returns: Interface key (name) in topology.
:rtype: str
:raises RuntimeError: If it is not possible to create bond interface on
the node.
"""
:returns: Interface key (name) in topology.
:rtype: str
:raises RuntimeError: If it is not possible to create bond interface on
the node.
"""
- cmd = u"bond_create"
+ cmd = u"bond_create
2
"
args = dict(
id=int(Constants.BITWISE_NON_ZERO),
use_custom_mac=bool(mac is not None),
args = dict(
id=int(Constants.BITWISE_NON_ZERO),
use_custom_mac=bool(mac is not None),
@@
-1078,7
+1085,8
@@
class InterfaceUtil:
LinkBondLoadBalanceAlgo,
f"BOND_API_LB_ALGO_{load_balance.upper()}"
).value,
LinkBondLoadBalanceAlgo,
f"BOND_API_LB_ALGO_{load_balance.upper()}"
).value,
- numa_only=False
+ numa_only=False,
+ enable_gso=gso
)
err_msg = f"Failed to create bond interface on host {node[u'host']}"
with PapiSocketExecutor(node) as papi_exec:
)
err_msg = f"Failed to create bond interface on host {node[u'host']}"
with PapiSocketExecutor(node) as papi_exec:
@@
-1202,7
+1210,7
@@
class InterfaceUtil:
node, u"set logging class rdma level debug"
)
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),
pci_addr = Topology.get_interface_pci_addr(node, if_key)
args = dict(
name=InterfaceUtil.pci_to_eth(node, pci_addr),
@@
-1211,6
+1219,9
@@
class InterfaceUtil:
rxq_size=rxq_size,
txq_size=txq_size,
mode=getattr(RdmaMode, f"RDMA_API_MODE_{mode.upper()}").value,
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:
)
err_msg = f"Failed to create RDMA interface on host {node[u'host']}"
with PapiSocketExecutor(node) as papi_exec:
@@
-1227,8
+1238,8
@@
class InterfaceUtil:
return Topology.get_interface_by_sw_index(node, sw_if_index)
@staticmethod
return Topology.get_interface_by_sw_index(node, sw_if_index)
@staticmethod
- def vpp_
enslave_physical_interface
(node, interface, bond_if):
- """
Enslave physical
interface to bond interface on VPP node.
+ def vpp_
add_bond_member
(node, interface, bond_if):
+ """
Add member
interface to bond interface on VPP node.
:param node: DUT node from topology.
:param interface: Physical interface key from topology file.
:param node: DUT node from topology.
:param interface: Physical interface key from topology file.
@@
-1236,18
+1247,18
@@
class InterfaceUtil:
:type node: dict
:type interface: str
:type bond_if: str
:type node: dict
:type interface: str
:type bond_if: str
- :raises RuntimeError: If it is not possible to
enslave physical
- interface
to bond interface
on the node.
+ :raises RuntimeError: If it is not possible to
add member to bond
+ interface on the node.
"""
"""
- cmd = u"bond_
enslave
"
+ cmd = u"bond_
add_member
"
args = dict(
sw_if_index=Topology.get_interface_sw_index(node, interface),
bond_sw_if_index=Topology.get_interface_sw_index(node, bond_if),
is_passive=False,
is_long_timeout=False
)
args = dict(
sw_if_index=Topology.get_interface_sw_index(node, interface),
bond_sw_if_index=Topology.get_interface_sw_index(node, bond_if),
is_passive=False,
is_long_timeout=False
)
- err_msg = f"Failed to
enslave physical interface {interface} to bond
" \
- f"
interface
{bond_if} on host {node[u'host']}"
+ err_msg = f"Failed to
add member {interface} to bond interface
" \
+ f"{bond_if} on host {node[u'host']}"
with PapiSocketExecutor(node) as papi_exec:
papi_exec.add(cmd, **args).get_reply(err_msg)
with PapiSocketExecutor(node) as papi_exec:
papi_exec.add(cmd, **args).get_reply(err_msg)
@@
-1260,7
+1271,7
@@
class InterfaceUtil:
:type node: dict
:type verbose: bool
"""
:type node: dict
:type verbose: bool
"""
- cmd = u"sw_
interface_bond
_dump"
+ cmd = u"sw_
bond_interface
_dump"
err_msg = f"Failed to get bond interface dump on host {node[u'host']}"
data = f"Bond data on node {node[u'host']}:\n"
err_msg = f"Failed to get bond interface dump on host {node[u'host']}"
data = f"Bond data on node {node[u'host']}:\n"
@@
-1275,26
+1286,26
@@
class InterfaceUtil:
data += u" load balance: {lb}\n".format(
lb=bond[u"lb"].name.replace(u"BOND_API_LB_ALGO_", u"").lower()
)
data += u" load balance: {lb}\n".format(
lb=bond[u"lb"].name.replace(u"BOND_API_LB_ALGO_", u"").lower()
)
- data += f" number of active
slaves: {bond[u'active_slave
s']}\n"
+ data += f" number of active
members: {bond[u'active_member
s']}\n"
if verbose:
if verbose:
-
slave_data = InterfaceUtil.vpp_bond_slave
_dump(
+
member_data = InterfaceUtil.vpp_bond_member
_dump(
node, Topology.get_interface_by_sw_index(
node, bond[u"sw_if_index"]
)
)
node, Topology.get_interface_by_sw_index(
node, bond[u"sw_if_index"]
)
)
- for
slave in slave
_data:
- if not
slave
[u"is_passive"]:
- data += f" {
slave
[u'interface_name']}\n"
- data += f" number of
slaves: {bond[u'slave
s']}\n"
+ for
member in member
_data:
+ if not
member
[u"is_passive"]:
+ data += f" {
member
[u'interface_name']}\n"
+ data += f" number of
members: {bond[u'member
s']}\n"
if verbose:
if verbose:
- for
slave in slave
_data:
- data += f" {
slave
[u'interface_name']}\n"
+ for
member in member
_data:
+ data += f" {
member
[u'interface_name']}\n"
data += f" interface id: {bond[u'id']}\n"
data += f" sw_if_index: {bond[u'sw_if_index']}\n"
logger.info(data)
@staticmethod
data += f" interface id: {bond[u'id']}\n"
data += f" sw_if_index: {bond[u'sw_if_index']}\n"
logger.info(data)
@staticmethod
- def vpp_bond_
slave
_dump(node, interface):
+ def vpp_bond_
member
_dump(node, interface):
"""Get bond interface slave(s) data on VPP node.
:param node: DUT node from topology.
"""Get bond interface slave(s) data on VPP node.
:param node: DUT node from topology.
@@
-1304,7
+1315,7
@@
class InterfaceUtil:
:returns: Bond slave interface data.
:rtype: dict
"""
:returns: Bond slave interface data.
:rtype: dict
"""
- cmd = u"sw_
interface_slav
e_dump"
+ cmd = u"sw_
member_interfac
e_dump"
args = dict(
sw_if_index=Topology.get_interface_sw_index(node, interface)
)
args = dict(
sw_if_index=Topology.get_interface_sw_index(node, interface)
)
@@
-1313,7
+1324,7
@@
class InterfaceUtil:
with PapiSocketExecutor(node) as papi_exec:
details = papi_exec.add(cmd, **args).get_details(err_msg)
with PapiSocketExecutor(node) as papi_exec:
details = papi_exec.add(cmd, **args).get_details(err_msg)
- logger.debug(f"
Slave
data:\n{details}")
+ logger.debug(f"
Member
data:\n{details}")
return details
@staticmethod
return details
@staticmethod
@@
-1701,17
+1712,29
@@
class InterfaceUtil:
papi_exec.add(cmd, **args).get_reply(err_msg)
@staticmethod
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.
"""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 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 node: dict
:type prefix: str
+ :type dp_worker_limit: Optional[int]
"""
worker_id = 0
worker_cnt = len(VPPUtil.vpp_show_threads(node)) - 1
"""
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):
if not worker_cnt:
return
for placement in InterfaceUtil.vpp_sw_interface_rx_placement_dump(node):
@@
-1725,15
+1748,31
@@
class InterfaceUtil:
worker_id += 1
@staticmethod
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.
"""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 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 nodes: dict
:type prefix: str
+ :type dp_worker_limit: Optional[int]
"""
for node in nodes.values():
if node[u"type"] == NodeType.DUT:
"""
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
+ )