From: Jozef Urbanovsky jurbanov@redhat.com
Hi,
This patchset adds OvSDPDKBondRecipe and fixes some issues with test tools required for the recipe. Patchset has been reviewed in internal downstream, before it was decided to split it to upstream and downstream.
It has been tested to be fully functional.
Jozef Urbanovsky (6): lnst.Recipes.ENRT.OvSDPDKBondRecipe: add new recipe lnst.Tests.TestPMD: add mode branching lnst.Tests.TRex: add __repr__ methods, expose module parameter lnst.RecipeCommon.Perf.Measurements.TRexFlowMeasurement: fixes requirements: add dataclasses package lnst.Recipes.ENRT.OvSDPDKBondRecipe: override *test_tweak methods
.../Perf/Measurements/TRexFlowMeasurement.py | 5 +- lnst/Recipes/ENRT/OvSDPDKBondRecipe.py | 257 ++++++++++++++++++ lnst/Recipes/ENRT/__init__.py | 1 + lnst/Tests/TRex.py | 27 ++ lnst/Tests/TestPMD.py | 36 ++- requirements.txt | 1 + 6 files changed, 315 insertions(+), 12 deletions(-) create mode 100644 lnst/Recipes/ENRT/OvSDPDKBondRecipe.py
From: Jozef Urbanovsky jurbanov@redhat.com
Signed-off-by: Jozef Urbanovsky jurbanov@redhat.com --- lnst/Recipes/ENRT/OvSDPDKBondRecipe.py | 248 +++++++++++++++++++++++++ lnst/Recipes/ENRT/__init__.py | 1 + 2 files changed, 249 insertions(+) create mode 100644 lnst/Recipes/ENRT/OvSDPDKBondRecipe.py
diff --git a/lnst/Recipes/ENRT/OvSDPDKBondRecipe.py b/lnst/Recipes/ENRT/OvSDPDKBondRecipe.py new file mode 100644 index 0000000..7e9a4cb --- /dev/null +++ b/lnst/Recipes/ENRT/OvSDPDKBondRecipe.py @@ -0,0 +1,248 @@ +import signal +from lnst.Common.Parameters import StrParam, IntParam, Param +from lnst.Controller import HostReq, DeviceReq, RecipeParam +from lnst.Controller.Namespace import Namespace +from lnst.Recipes.ENRT.BaseEnrtRecipe import BaseEnrtRecipe +from lnst.Recipes.ENRT.ConfigMixins.CommonHWSubConfigMixin import ( + CommonHWSubConfigMixin) +from dataclasses import dataclass +from lnst.Common.IpAddress import ipaddress +from lnst.Tests.TestPMD import TestPMD + +from lnst.RecipeCommon.Perf.Recipe import RecipeConf as PerfRecipeConf +from lnst.RecipeCommon.Perf.Measurements import Flow as PerfFlow +from lnst.RecipeCommon.Perf.Measurements import TRexFlowMeasurement +from lnst.RecipeCommon.Perf.Measurements import StatCPUMeasurement + + +@dataclass +class DummyEthDevice: + bus_info: str + hwaddr: str + _id: str + ips: list + + +@dataclass +class DummyRecipeConfig: + eth0: DummyEthDevice + eth1: DummyEthDevice + netns: Namespace + testpmd: None + test_br: str = "test_bridge" + bond_br: str = "bond_bridge" + + +class OvSDPDKBondRecipe(CommonHWSubConfigMixin, BaseEnrtRecipe): + host1 = HostReq() + host1.eth0 = DeviceReq(label="to_switch", driver=RecipeParam("driver")) + host1.eth1 = DeviceReq(label="to_switch", driver=RecipeParam("driver")) + + host2 = HostReq() + host2.eth0 = DeviceReq(label="to_switch", driver=RecipeParam("driver")) + host2.eth1 = DeviceReq(label="to_switch", driver=RecipeParam("driver")) + + bonding_mode = StrParam(mandatory=True) + lacp_mode = StrParam(mandatory=True) + + hugepages = IntParam(default=12) + dpdk_socket_mem = IntParam(default=1024) + dpdk_lcore_mask = StrParam(mandatory=True) + pmd_cpu_mask = StrParam(mandatory=True) + + testpmd_cores = StrParam(mandatory=True) + testpmd_dpdk_cores = StrParam(mandatory=True) + + trex_dpdk_cores = StrParam(mandatory=True) + trex_dir = StrParam(mandatory=True) + + perf_duration = IntParam(default=60) + perf_iterations = IntParam(default=5) + perf_msg_size = IntParam(default=64) + + cpu_perf_tool = Param(default=StatCPUMeasurement) + net_perf_tool = Param(default=TRexFlowMeasurement) + + def test_wide_configuration(self): + host1, host2 = self.matched.host1, self.matched.host2 + + net_addr_0 = "192.168.101" + net_addr6_0 = "fc00:0:0:0" + + net_addr_1 = "192.168.102" + net_addr6_1 = "fc00:0:0:0" + + for i, host in enumerate([host1, host2]): + host.dummy_cfg = DummyRecipeConfig( + eth0=DummyEthDevice(host.eth0.bus_info, host.eth0.hwaddr, _id="eth" + str(i), + ips=[ipaddress(net_addr_0 + "." + str(i + 1) + "/24"), + ipaddress(net_addr6_0 + "::" + str(i + 1) + "/64")] + ), + eth1=DummyEthDevice(host.eth1.bus_info, host.eth1.hwaddr, _id="eth" + str(i + 1), + ips=[ipaddress(net_addr_1 + "." + str(i + 1) + "/24"), + ipaddress(net_addr6_1 + "::" + str(i + 1) + "/64")] + ), + + netns=host, + testpmd=None + ) + + host.run(f"echo -n {self.params.hugepages} /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages") + host.run("modprobe vfio-pci") + + host.run(f"driverctl set-override {host.dummy_cfg.eth0.bus_info} vfio-pci") + host.run(f"driverctl set-override {host.dummy_cfg.eth1.bus_info} vfio-pci") + + if i == 0: + self.ovs_dpdk_bridge_configuration(host) + + host.dummy_cfg.testpmd = host.run( + TestPMD( + coremask=self.params.testpmd_cores, + pmd_coremask=self.params.testpmd_dpdk_cores, + mode="macswap", + nics=["vhost0", "vhost1"]), + bg=True) + + configuration = super().test_wide_configuration() + return configuration + + def ovs_dpdk_bridge_configuration(self, host): + host.run("systemctl enable openvswitch") + host.run("systemctl start openvswitch") + host.run(f"ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-socket-mem=" + f"{self.params.dpdk_socket_mem}") + host.run(f"ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-lcore-mask=" + f"{self.params.dpdk_lcore_mask}") + host.run(f"ovs-vsctl --no-wait set Open_vSwitch . other_config:pmd-cpu-mask=" + f"{self.params.pmd_cpu_mask}") + host.run("ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true") + + host.run(f"ovs-vsctl add-br {host.dummy_cfg.bond_br} " + f"-- set bridge {host.dummy_cfg.bond_br} datapath_type=netdev") + + host.run(f"ovs-vsctl add-bond {host.dummy_cfg.bond_br} dpdkbond dpdk0 dpdk1 " + f"bond_mode={self.params.bonding_mode} lacp={self.params.lacp_mode} " + f"-- set Interface dpdk0 type=dpdk options:dpdk-devargs={host.dummy_cfg.eth0.bus_info} " + f"-- set Interface dpdk1 type=dpdk options:dpdk-devargs={host.dummy_cfg.eth1.bus_info}") + + host.run(f"ovs-vsctl add-br {host.dummy_cfg.test_br} " + f"-- set bridge {host.dummy_cfg.test_br} datapath_type=netdev") + + host.run(f"ovs-vsctl add-port {host.dummy_cfg.test_br} vhost0 " + f"-- set Interface vhost0 type=dpdkvhostuser") + host.run(f"ovs-vsctl add-port {host.dummy_cfg.test_br} vhost1 " + f"-- set Interface vhost1 type=dpdkvhostuser") + + host.run(f"ovs-vsctl -- add-port {host.dummy_cfg.test_br} dpdk_patch " + "-- set interface dpdk_patch type=patch options:peer=test_patch " + f"-- add-port {host.dummy_cfg.bond_br} test_patch " + "-- set interface test_patch type=patch options:peer=dpdk_patch") + + host.run(f"ovs-ofctl mod-port {host.dummy_cfg.bond_br} dpdk0 up") + host.run(f"ovs-ofctl mod-port {host.dummy_cfg.bond_br} dpdk1 up") + + for bridge in (host.dummy_cfg.test_br, host.dummy_cfg.bond_br): + host.run(f"ip l set {bridge} up") + host.run(f"ovs-ofctl del-flows {bridge}") + host.run(f"ovs-ofctl add-flow {bridge} actions=NORMAL") + + def generate_perf_configurations(self, config): + host1, host2 = self.matched.host1, self.matched.host2 + testpmd_nics = [host1.dummy_cfg.eth0, host1.dummy_cfg.eth1] + trex_nics = [host2.dummy_cfg.eth0, host2.dummy_cfg.eth1] + flows = [] + for trex_nic, testpmd_nic in zip(trex_nics, testpmd_nics): + trex_bind = dict(mac_addr=trex_nic.hwaddr, + pci_addr=trex_nic.bus_info, + ip_addr=trex_nic.ips[0], + family=trex_nic.ips[0].family) + testpmd_bind = dict(mac_addr=testpmd_nic.hwaddr, + pci_addr=testpmd_nic.bus_info, + ip_addr=testpmd_nic.ips[0], + family=testpmd_nic.ips[0].family) + flows.append(PerfFlow( + type="UDPMultiflow", + generator=host2, + generator_nic=trex_nic, + generator_bind=trex_bind, + receiver=host1, + receiver_nic=testpmd_nic, + receiver_bind=testpmd_bind, + msg_size=self.params.perf_msg_size, + duration=self.params.perf_duration, + parallel_streams=1, + cpupin=None)) + + perf_recipe_conf = dict( + recipe_config=config, + flows=flows, + ) + + cpu_measurement = self.params.cpu_perf_tool([host1, host2], + perf_recipe_conf) + + flows_measurement = TRexFlowMeasurement( + flows, + self.params.trex_dir, + self.params.trex_dpdk_cores.split(","), + perf_recipe_conf, + ) + perf_conf = PerfRecipeConf( + measurements=[ + cpu_measurement, + flows_measurement, + ], + iterations=self.params.perf_iterations, + ) + perf_conf.register_evaluators(cpu_measurement, self.cpu_perf_evaluators) + perf_conf.register_evaluators(flows_measurement, self.net_perf_evaluators) + return perf_conf + + def do_perf_tests(self, recipe_config): + perf_config = self.generate_perf_configurations(recipe_config) + result = self.perf_test(perf_config) + self.perf_report_and_evaluate(result) + + def generate_test_wide_description(self, config): + desc = super().generate_test_wide_description(config) + host1, host2 = self.matched.host1, self.matched.host2 + for i, host in enumerate([host1, host2]): + desc += [f"Configured host{i} interfaces with bus info: {host.dummy_cfg.eth0.bus_info} " + f"and {host.dummy_cfg.eth1.bus_info} to be controlled by vfio-pci"] + if i == 1: + desc += [ + f"Created OvS bridges: {host.dummy_cfg.test_br} and {host.dummy_cfg.bond_br} on host{i} " + f"set with datapath_type to netdev", + f"Created dpdk bond on {host.dummy_cfg.bond_br} with bonding_mode set to " + f"{self.params.bonding_mode} using lacp_mode set to " + f"{self.params.lacp_mode}", + f"Interconnected OvS bridges with patch ports: test_patch and dpdk_patch", + f"Deleted all flows on both bridges and created a new one with "actions=NORMAL"", + f"TestPMD in a forward-mode macswap started on the host{i} {host.dummy_cfg.test_br} vhost0 port"] + + return desc + + def test_wide_deconfiguration(self, config): + host1, host2 = self.matched.host1, self.matched.host2 + + testpmd = host1.dummy_cfg.testpmd + if testpmd: + testpmd.kill(signal.SIGINT) + testpmd.wait() + + host1.run(f"ovs-vsctl del-br {host1.dummy_cfg.test_br}") + host1.run(f"ovs-vsctl del-br {host1.dummy_cfg.bond_br}") + + host1.run(f"driverctl unset-override {host1.dummy_cfg.eth0.bus_info} & sleep 1; systemctl restart openvswitch") + host1.run(f"driverctl unset-override {host1.dummy_cfg.eth1.bus_info} & sleep 1; systemctl restart openvswitch") + host1.run(f"ip l del {host1.dummy_cfg.test_br}") + + host2.run(f"driverctl unset-override {host2.dummy_cfg.eth0.bus_info}") + host2.run(f"driverctl unset-override {host2.dummy_cfg.eth1.bus_info}") + + def generate_ping_endpoints(self, config): + return [] + + def generate_perf_endpoints(self, config): + return [(self.matched.host1.dummy_cfg, self.matched.host2.dummy_cfg)] diff --git a/lnst/Recipes/ENRT/__init__.py b/lnst/Recipes/ENRT/__init__.py index 89d6133..e3c7d1e 100644 --- a/lnst/Recipes/ENRT/__init__.py +++ b/lnst/Recipes/ENRT/__init__.py @@ -58,6 +58,7 @@ from lnst.Recipes.ENRT.IpsecEspAeadRecipe import IpsecEspAeadRecipe from lnst.Recipes.ENRT.IpsecEspAhCompRecipe import IpsecEspAhCompRecipe from lnst.Recipes.ENRT.NoVirtOvsVxlanRecipe import NoVirtOvsVxlanRecipe from lnst.Recipes.ENRT.OvS_DPDK_PvP import OvSDPDKPvPRecipe +from lnst.Recipes.ENRT.OvSDPDKBondRecipe import OvSDPDKBondRecipe from lnst.Recipes.ENRT.PingFloodRecipe import PingFloodRecipe from lnst.Recipes.ENRT.SimpleMacsecRecipe import SimpleMacsecRecipe from lnst.Recipes.ENRT.ShortLivedConnectionsRecipe import ShortLivedConnectionsRecipe
Mon, Dec 14, 2020 at 11:59:26AM CET, jurbanov@redhat.com wrote:
From: Jozef Urbanovsky jurbanov@redhat.com
Signed-off-by: Jozef Urbanovsky jurbanov@redhat.com
lnst/Recipes/ENRT/OvSDPDKBondRecipe.py | 248 +++++++++++++++++++++++++ lnst/Recipes/ENRT/__init__.py | 1 + 2 files changed, 249 insertions(+) create mode 100644 lnst/Recipes/ENRT/OvSDPDKBondRecipe.py
diff --git a/lnst/Recipes/ENRT/OvSDPDKBondRecipe.py b/lnst/Recipes/ENRT/OvSDPDKBondRecipe.py new file mode 100644 index 0000000..7e9a4cb --- /dev/null +++ b/lnst/Recipes/ENRT/OvSDPDKBondRecipe.py @@ -0,0 +1,248 @@ +import signal +from lnst.Common.Parameters import StrParam, IntParam, Param +from lnst.Controller import HostReq, DeviceReq, RecipeParam +from lnst.Controller.Namespace import Namespace +from lnst.Recipes.ENRT.BaseEnrtRecipe import BaseEnrtRecipe +from lnst.Recipes.ENRT.ConfigMixins.CommonHWSubConfigMixin import (
- CommonHWSubConfigMixin)
+from dataclasses import dataclass +from lnst.Common.IpAddress import ipaddress +from lnst.Tests.TestPMD import TestPMD
+from lnst.RecipeCommon.Perf.Recipe import RecipeConf as PerfRecipeConf +from lnst.RecipeCommon.Perf.Measurements import Flow as PerfFlow +from lnst.RecipeCommon.Perf.Measurements import TRexFlowMeasurement +from lnst.RecipeCommon.Perf.Measurements import StatCPUMeasurement
+@dataclass +class DummyEthDevice:
- bus_info: str
- hwaddr: str
- _id: str
- ips: list
+@dataclass +class DummyRecipeConfig:
- eth0: DummyEthDevice
- eth1: DummyEthDevice
- netns: Namespace
- testpmd: None
- test_br: str = "test_bridge"
- bond_br: str = "bond_bridge"
+class OvSDPDKBondRecipe(CommonHWSubConfigMixin, BaseEnrtRecipe):
- host1 = HostReq()
- host1.eth0 = DeviceReq(label="to_switch", driver=RecipeParam("driver"))
- host1.eth1 = DeviceReq(label="to_switch", driver=RecipeParam("driver"))
- host2 = HostReq()
- host2.eth0 = DeviceReq(label="to_switch", driver=RecipeParam("driver"))
- host2.eth1 = DeviceReq(label="to_switch", driver=RecipeParam("driver"))
- bonding_mode = StrParam(mandatory=True)
- lacp_mode = StrParam(mandatory=True)
- hugepages = IntParam(default=12)
- dpdk_socket_mem = IntParam(default=1024)
- dpdk_lcore_mask = StrParam(mandatory=True)
- pmd_cpu_mask = StrParam(mandatory=True)
- testpmd_cores = StrParam(mandatory=True)
- testpmd_dpdk_cores = StrParam(mandatory=True)
- trex_dpdk_cores = StrParam(mandatory=True)
- trex_dir = StrParam(mandatory=True)
- perf_duration = IntParam(default=60)
- perf_iterations = IntParam(default=5)
- perf_msg_size = IntParam(default=64)
- cpu_perf_tool = Param(default=StatCPUMeasurement)
- net_perf_tool = Param(default=TRexFlowMeasurement)
- def test_wide_configuration(self):
host1, host2 = self.matched.host1, self.matched.host2
net_addr_0 = "192.168.101"
net_addr6_0 = "fc00:0:0:0"
net_addr_1 = "192.168.102"
net_addr6_1 = "fc00:0:0:0"
for i, host in enumerate([host1, host2]):
host.dummy_cfg = DummyRecipeConfig(
eth0=DummyEthDevice(host.eth0.bus_info, host.eth0.hwaddr, _id="eth" + str(i),
ips=[ipaddress(net_addr_0 + "." + str(i + 1) + "/24"),
ipaddress(net_addr6_0 + "::" + str(i + 1) + "/64")]
),
eth1=DummyEthDevice(host.eth1.bus_info, host.eth1.hwaddr, _id="eth" + str(i + 1),
ips=[ipaddress(net_addr_1 + "." + str(i + 1) + "/24"),
ipaddress(net_addr6_1 + "::" + str(i + 1) + "/64")]
),
netns=host,
testpmd=None
)
host.run(f"echo -n {self.params.hugepages} /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages")
host.run("modprobe vfio-pci")
host.run(f"driverctl set-override {host.dummy_cfg.eth0.bus_info} vfio-pci")
host.run(f"driverctl set-override {host.dummy_cfg.eth1.bus_info} vfio-pci")
if i == 0:
self.ovs_dpdk_bridge_configuration(host)
host.dummy_cfg.testpmd = host.run(
TestPMD(
coremask=self.params.testpmd_cores,
pmd_coremask=self.params.testpmd_dpdk_cores,
mode="macswap",
nics=["vhost0", "vhost1"]),
bg=True)
Would it make more sense to move the content in the if statement out of the loop? That way you can remove the "if" completely.
configuration = super().test_wide_configuration()
return configuration
- def ovs_dpdk_bridge_configuration(self, host):
host.run("systemctl enable openvswitch")
host.run("systemctl start openvswitch")
host.run(f"ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-socket-mem="
f"{self.params.dpdk_socket_mem}")
host.run(f"ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-lcore-mask="
f"{self.params.dpdk_lcore_mask}")
host.run(f"ovs-vsctl --no-wait set Open_vSwitch . other_config:pmd-cpu-mask="
f"{self.params.pmd_cpu_mask}")
host.run("ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true")
host.run(f"ovs-vsctl add-br {host.dummy_cfg.bond_br} "
f"-- set bridge {host.dummy_cfg.bond_br} datapath_type=netdev")
host.run(f"ovs-vsctl add-bond {host.dummy_cfg.bond_br} dpdkbond dpdk0 dpdk1 "
f"bond_mode={self.params.bonding_mode} lacp={self.params.lacp_mode} "
f"-- set Interface dpdk0 type=dpdk options:dpdk-devargs={host.dummy_cfg.eth0.bus_info} "
f"-- set Interface dpdk1 type=dpdk options:dpdk-devargs={host.dummy_cfg.eth1.bus_info}")
host.run(f"ovs-vsctl add-br {host.dummy_cfg.test_br} "
f"-- set bridge {host.dummy_cfg.test_br} datapath_type=netdev")
host.run(f"ovs-vsctl add-port {host.dummy_cfg.test_br} vhost0 "
f"-- set Interface vhost0 type=dpdkvhostuser")
host.run(f"ovs-vsctl add-port {host.dummy_cfg.test_br} vhost1 "
f"-- set Interface vhost1 type=dpdkvhostuser")
host.run(f"ovs-vsctl -- add-port {host.dummy_cfg.test_br} dpdk_patch "
"-- set interface dpdk_patch type=patch options:peer=test_patch "
f"-- add-port {host.dummy_cfg.bond_br} test_patch "
"-- set interface test_patch type=patch options:peer=dpdk_patch")
host.run(f"ovs-ofctl mod-port {host.dummy_cfg.bond_br} dpdk0 up")
host.run(f"ovs-ofctl mod-port {host.dummy_cfg.bond_br} dpdk1 up")
for bridge in (host.dummy_cfg.test_br, host.dummy_cfg.bond_br):
host.run(f"ip l set {bridge} up")
host.run(f"ovs-ofctl del-flows {bridge}")
host.run(f"ovs-ofctl add-flow {bridge} actions=NORMAL")
- def generate_perf_configurations(self, config):
host1, host2 = self.matched.host1, self.matched.host2
testpmd_nics = [host1.dummy_cfg.eth0, host1.dummy_cfg.eth1]
trex_nics = [host2.dummy_cfg.eth0, host2.dummy_cfg.eth1]
flows = []
for trex_nic, testpmd_nic in zip(trex_nics, testpmd_nics):
trex_bind = dict(mac_addr=trex_nic.hwaddr,
pci_addr=trex_nic.bus_info,
ip_addr=trex_nic.ips[0],
family=trex_nic.ips[0].family)
testpmd_bind = dict(mac_addr=testpmd_nic.hwaddr,
pci_addr=testpmd_nic.bus_info,
ip_addr=testpmd_nic.ips[0],
family=testpmd_nic.ips[0].family)
flows.append(PerfFlow(
type="UDPMultiflow",
generator=host2,
generator_nic=trex_nic,
generator_bind=trex_bind,
receiver=host1,
receiver_nic=testpmd_nic,
receiver_bind=testpmd_bind,
msg_size=self.params.perf_msg_size,
duration=self.params.perf_duration,
parallel_streams=1,
cpupin=None))
perf_recipe_conf = dict(
recipe_config=config,
flows=flows,
)
cpu_measurement = self.params.cpu_perf_tool([host1, host2],
perf_recipe_conf)
flows_measurement = TRexFlowMeasurement(
flows,
self.params.trex_dir,
self.params.trex_dpdk_cores.split(","),
perf_recipe_conf,
)
perf_conf = PerfRecipeConf(
measurements=[
cpu_measurement,
flows_measurement,
],
iterations=self.params.perf_iterations,
)
perf_conf.register_evaluators(cpu_measurement, self.cpu_perf_evaluators)
perf_conf.register_evaluators(flows_measurement, self.net_perf_evaluators)
return perf_conf
- def do_perf_tests(self, recipe_config):
perf_config = self.generate_perf_configurations(recipe_config)
result = self.perf_test(perf_config)
self.perf_report_and_evaluate(result)
- def generate_test_wide_description(self, config):
desc = super().generate_test_wide_description(config)
host1, host2 = self.matched.host1, self.matched.host2
for i, host in enumerate([host1, host2]):
desc += [f"Configured host{i} interfaces with bus info: {host.dummy_cfg.eth0.bus_info} "
f"and {host.dummy_cfg.eth1.bus_info} to be controlled by vfio-pci"]
if i == 1:
desc += [
f"Created OvS bridges: {host.dummy_cfg.test_br} and {host.dummy_cfg.bond_br} on host{i} "
f"set with datapath_type to netdev",
f"Created dpdk bond on {host.dummy_cfg.bond_br} with bonding_mode set to "
f"{self.params.bonding_mode} using lacp_mode set to "
f"{self.params.lacp_mode}",
f"Interconnected OvS bridges with patch ports: test_patch and dpdk_patch",
f"Deleted all flows on both bridges and created a new one with \"actions=NORMAL\"",
f"TestPMD in a forward-mode macswap started on the host{i} {host.dummy_cfg.test_br} vhost0 port"]
I think the same applies here. It's not a big deal, if you're fine with that, we can keep it as it is.
return desc
- def test_wide_deconfiguration(self, config):
host1, host2 = self.matched.host1, self.matched.host2
testpmd = host1.dummy_cfg.testpmd
if testpmd:
testpmd.kill(signal.SIGINT)
testpmd.wait()
host1.run(f"ovs-vsctl del-br {host1.dummy_cfg.test_br}")
host1.run(f"ovs-vsctl del-br {host1.dummy_cfg.bond_br}")
host1.run(f"driverctl unset-override {host1.dummy_cfg.eth0.bus_info} & sleep 1; systemctl restart openvswitch")
host1.run(f"driverctl unset-override {host1.dummy_cfg.eth1.bus_info} & sleep 1; systemctl restart openvswitch")
host1.run(f"ip l del {host1.dummy_cfg.test_br}")
host2.run(f"driverctl unset-override {host2.dummy_cfg.eth0.bus_info}")
host2.run(f"driverctl unset-override {host2.dummy_cfg.eth1.bus_info}")
- def generate_ping_endpoints(self, config):
return []
- def generate_perf_endpoints(self, config):
return [(self.matched.host1.dummy_cfg, self.matched.host2.dummy_cfg)]
diff --git a/lnst/Recipes/ENRT/__init__.py b/lnst/Recipes/ENRT/__init__.py index 89d6133..e3c7d1e 100644 --- a/lnst/Recipes/ENRT/__init__.py +++ b/lnst/Recipes/ENRT/__init__.py @@ -58,6 +58,7 @@ from lnst.Recipes.ENRT.IpsecEspAeadRecipe import IpsecEspAeadRecipe from lnst.Recipes.ENRT.IpsecEspAhCompRecipe import IpsecEspAhCompRecipe from lnst.Recipes.ENRT.NoVirtOvsVxlanRecipe import NoVirtOvsVxlanRecipe from lnst.Recipes.ENRT.OvS_DPDK_PvP import OvSDPDKPvPRecipe +from lnst.Recipes.ENRT.OvSDPDKBondRecipe import OvSDPDKBondRecipe from lnst.Recipes.ENRT.PingFloodRecipe import PingFloodRecipe from lnst.Recipes.ENRT.SimpleMacsecRecipe import SimpleMacsecRecipe from lnst.Recipes.ENRT.ShortLivedConnectionsRecipe import ShortLivedConnectionsRecipe -- 2.28.0 _______________________________________________ LNST-developers mailing list -- lnst-developers@lists.fedorahosted.org To unsubscribe send an email to lnst-developers-leave@lists.fedorahosted.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/lnst-developers@lists.fedorahos...
One more note. Since this patch adds a completely new recipe it would be good to include at least some description what the test does.
Alternatively you could add a docstring that would provide this information.
J.
Mon, Dec 14, 2020 at 11:59:26AM CET, jurbanov@redhat.com wrote:
From: Jozef Urbanovsky jurbanov@redhat.com
Signed-off-by: Jozef Urbanovsky jurbanov@redhat.com
lnst/Recipes/ENRT/OvSDPDKBondRecipe.py | 248 +++++++++++++++++++++++++ lnst/Recipes/ENRT/__init__.py | 1 + 2 files changed, 249 insertions(+) create mode 100644 lnst/Recipes/ENRT/OvSDPDKBondRecipe.py
diff --git a/lnst/Recipes/ENRT/OvSDPDKBondRecipe.py b/lnst/Recipes/ENRT/OvSDPDKBondRecipe.py new file mode 100644 index 0000000..7e9a4cb --- /dev/null +++ b/lnst/Recipes/ENRT/OvSDPDKBondRecipe.py @@ -0,0 +1,248 @@ +import signal +from lnst.Common.Parameters import StrParam, IntParam, Param +from lnst.Controller import HostReq, DeviceReq, RecipeParam +from lnst.Controller.Namespace import Namespace +from lnst.Recipes.ENRT.BaseEnrtRecipe import BaseEnrtRecipe +from lnst.Recipes.ENRT.ConfigMixins.CommonHWSubConfigMixin import (
- CommonHWSubConfigMixin)
+from dataclasses import dataclass +from lnst.Common.IpAddress import ipaddress +from lnst.Tests.TestPMD import TestPMD
+from lnst.RecipeCommon.Perf.Recipe import RecipeConf as PerfRecipeConf +from lnst.RecipeCommon.Perf.Measurements import Flow as PerfFlow +from lnst.RecipeCommon.Perf.Measurements import TRexFlowMeasurement +from lnst.RecipeCommon.Perf.Measurements import StatCPUMeasurement
+@dataclass +class DummyEthDevice:
- bus_info: str
- hwaddr: str
- _id: str
- ips: list
+@dataclass +class DummyRecipeConfig:
- eth0: DummyEthDevice
- eth1: DummyEthDevice
- netns: Namespace
- testpmd: None
- test_br: str = "test_bridge"
- bond_br: str = "bond_bridge"
+class OvSDPDKBondRecipe(CommonHWSubConfigMixin, BaseEnrtRecipe):
- host1 = HostReq()
- host1.eth0 = DeviceReq(label="to_switch", driver=RecipeParam("driver"))
- host1.eth1 = DeviceReq(label="to_switch", driver=RecipeParam("driver"))
- host2 = HostReq()
- host2.eth0 = DeviceReq(label="to_switch", driver=RecipeParam("driver"))
- host2.eth1 = DeviceReq(label="to_switch", driver=RecipeParam("driver"))
- bonding_mode = StrParam(mandatory=True)
- lacp_mode = StrParam(mandatory=True)
- hugepages = IntParam(default=12)
- dpdk_socket_mem = IntParam(default=1024)
- dpdk_lcore_mask = StrParam(mandatory=True)
- pmd_cpu_mask = StrParam(mandatory=True)
- testpmd_cores = StrParam(mandatory=True)
- testpmd_dpdk_cores = StrParam(mandatory=True)
- trex_dpdk_cores = StrParam(mandatory=True)
- trex_dir = StrParam(mandatory=True)
- perf_duration = IntParam(default=60)
- perf_iterations = IntParam(default=5)
- perf_msg_size = IntParam(default=64)
- cpu_perf_tool = Param(default=StatCPUMeasurement)
- net_perf_tool = Param(default=TRexFlowMeasurement)
- def test_wide_configuration(self):
host1, host2 = self.matched.host1, self.matched.host2
net_addr_0 = "192.168.101"
net_addr6_0 = "fc00:0:0:0"
net_addr_1 = "192.168.102"
net_addr6_1 = "fc00:0:0:0"
for i, host in enumerate([host1, host2]):
host.dummy_cfg = DummyRecipeConfig(
eth0=DummyEthDevice(host.eth0.bus_info, host.eth0.hwaddr, _id="eth" + str(i),
ips=[ipaddress(net_addr_0 + "." + str(i + 1) + "/24"),
ipaddress(net_addr6_0 + "::" + str(i + 1) + "/64")]
),
eth1=DummyEthDevice(host.eth1.bus_info, host.eth1.hwaddr, _id="eth" + str(i + 1),
ips=[ipaddress(net_addr_1 + "." + str(i + 1) + "/24"),
ipaddress(net_addr6_1 + "::" + str(i + 1) + "/64")]
),
netns=host,
testpmd=None
)
host.run(f"echo -n {self.params.hugepages} /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages")
host.run("modprobe vfio-pci")
host.run(f"driverctl set-override {host.dummy_cfg.eth0.bus_info} vfio-pci")
host.run(f"driverctl set-override {host.dummy_cfg.eth1.bus_info} vfio-pci")
if i == 0:
self.ovs_dpdk_bridge_configuration(host)
host.dummy_cfg.testpmd = host.run(
TestPMD(
coremask=self.params.testpmd_cores,
pmd_coremask=self.params.testpmd_dpdk_cores,
mode="macswap",
nics=["vhost0", "vhost1"]),
bg=True)
configuration = super().test_wide_configuration()
return configuration
- def ovs_dpdk_bridge_configuration(self, host):
host.run("systemctl enable openvswitch")
host.run("systemctl start openvswitch")
host.run(f"ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-socket-mem="
f"{self.params.dpdk_socket_mem}")
host.run(f"ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-lcore-mask="
f"{self.params.dpdk_lcore_mask}")
host.run(f"ovs-vsctl --no-wait set Open_vSwitch . other_config:pmd-cpu-mask="
f"{self.params.pmd_cpu_mask}")
host.run("ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true")
host.run(f"ovs-vsctl add-br {host.dummy_cfg.bond_br} "
f"-- set bridge {host.dummy_cfg.bond_br} datapath_type=netdev")
host.run(f"ovs-vsctl add-bond {host.dummy_cfg.bond_br} dpdkbond dpdk0 dpdk1 "
f"bond_mode={self.params.bonding_mode} lacp={self.params.lacp_mode} "
f"-- set Interface dpdk0 type=dpdk options:dpdk-devargs={host.dummy_cfg.eth0.bus_info} "
f"-- set Interface dpdk1 type=dpdk options:dpdk-devargs={host.dummy_cfg.eth1.bus_info}")
host.run(f"ovs-vsctl add-br {host.dummy_cfg.test_br} "
f"-- set bridge {host.dummy_cfg.test_br} datapath_type=netdev")
host.run(f"ovs-vsctl add-port {host.dummy_cfg.test_br} vhost0 "
f"-- set Interface vhost0 type=dpdkvhostuser")
host.run(f"ovs-vsctl add-port {host.dummy_cfg.test_br} vhost1 "
f"-- set Interface vhost1 type=dpdkvhostuser")
host.run(f"ovs-vsctl -- add-port {host.dummy_cfg.test_br} dpdk_patch "
"-- set interface dpdk_patch type=patch options:peer=test_patch "
f"-- add-port {host.dummy_cfg.bond_br} test_patch "
"-- set interface test_patch type=patch options:peer=dpdk_patch")
host.run(f"ovs-ofctl mod-port {host.dummy_cfg.bond_br} dpdk0 up")
host.run(f"ovs-ofctl mod-port {host.dummy_cfg.bond_br} dpdk1 up")
for bridge in (host.dummy_cfg.test_br, host.dummy_cfg.bond_br):
host.run(f"ip l set {bridge} up")
host.run(f"ovs-ofctl del-flows {bridge}")
host.run(f"ovs-ofctl add-flow {bridge} actions=NORMAL")
- def generate_perf_configurations(self, config):
host1, host2 = self.matched.host1, self.matched.host2
testpmd_nics = [host1.dummy_cfg.eth0, host1.dummy_cfg.eth1]
trex_nics = [host2.dummy_cfg.eth0, host2.dummy_cfg.eth1]
flows = []
for trex_nic, testpmd_nic in zip(trex_nics, testpmd_nics):
trex_bind = dict(mac_addr=trex_nic.hwaddr,
pci_addr=trex_nic.bus_info,
ip_addr=trex_nic.ips[0],
family=trex_nic.ips[0].family)
testpmd_bind = dict(mac_addr=testpmd_nic.hwaddr,
pci_addr=testpmd_nic.bus_info,
ip_addr=testpmd_nic.ips[0],
family=testpmd_nic.ips[0].family)
flows.append(PerfFlow(
type="UDPMultiflow",
generator=host2,
generator_nic=trex_nic,
generator_bind=trex_bind,
receiver=host1,
receiver_nic=testpmd_nic,
receiver_bind=testpmd_bind,
msg_size=self.params.perf_msg_size,
duration=self.params.perf_duration,
parallel_streams=1,
cpupin=None))
perf_recipe_conf = dict(
recipe_config=config,
flows=flows,
)
cpu_measurement = self.params.cpu_perf_tool([host1, host2],
perf_recipe_conf)
flows_measurement = TRexFlowMeasurement(
flows,
self.params.trex_dir,
self.params.trex_dpdk_cores.split(","),
perf_recipe_conf,
)
perf_conf = PerfRecipeConf(
measurements=[
cpu_measurement,
flows_measurement,
],
iterations=self.params.perf_iterations,
)
perf_conf.register_evaluators(cpu_measurement, self.cpu_perf_evaluators)
perf_conf.register_evaluators(flows_measurement, self.net_perf_evaluators)
return perf_conf
- def do_perf_tests(self, recipe_config):
perf_config = self.generate_perf_configurations(recipe_config)
result = self.perf_test(perf_config)
self.perf_report_and_evaluate(result)
- def generate_test_wide_description(self, config):
desc = super().generate_test_wide_description(config)
host1, host2 = self.matched.host1, self.matched.host2
for i, host in enumerate([host1, host2]):
desc += [f"Configured host{i} interfaces with bus info: {host.dummy_cfg.eth0.bus_info} "
f"and {host.dummy_cfg.eth1.bus_info} to be controlled by vfio-pci"]
if i == 1:
desc += [
f"Created OvS bridges: {host.dummy_cfg.test_br} and {host.dummy_cfg.bond_br} on host{i} "
f"set with datapath_type to netdev",
f"Created dpdk bond on {host.dummy_cfg.bond_br} with bonding_mode set to "
f"{self.params.bonding_mode} using lacp_mode set to "
f"{self.params.lacp_mode}",
f"Interconnected OvS bridges with patch ports: test_patch and dpdk_patch",
f"Deleted all flows on both bridges and created a new one with \"actions=NORMAL\"",
f"TestPMD in a forward-mode macswap started on the host{i} {host.dummy_cfg.test_br} vhost0 port"]
return desc
- def test_wide_deconfiguration(self, config):
host1, host2 = self.matched.host1, self.matched.host2
testpmd = host1.dummy_cfg.testpmd
if testpmd:
testpmd.kill(signal.SIGINT)
testpmd.wait()
host1.run(f"ovs-vsctl del-br {host1.dummy_cfg.test_br}")
host1.run(f"ovs-vsctl del-br {host1.dummy_cfg.bond_br}")
host1.run(f"driverctl unset-override {host1.dummy_cfg.eth0.bus_info} & sleep 1; systemctl restart openvswitch")
host1.run(f"driverctl unset-override {host1.dummy_cfg.eth1.bus_info} & sleep 1; systemctl restart openvswitch")
host1.run(f"ip l del {host1.dummy_cfg.test_br}")
host2.run(f"driverctl unset-override {host2.dummy_cfg.eth0.bus_info}")
host2.run(f"driverctl unset-override {host2.dummy_cfg.eth1.bus_info}")
- def generate_ping_endpoints(self, config):
return []
- def generate_perf_endpoints(self, config):
return [(self.matched.host1.dummy_cfg, self.matched.host2.dummy_cfg)]
diff --git a/lnst/Recipes/ENRT/__init__.py b/lnst/Recipes/ENRT/__init__.py index 89d6133..e3c7d1e 100644 --- a/lnst/Recipes/ENRT/__init__.py +++ b/lnst/Recipes/ENRT/__init__.py @@ -58,6 +58,7 @@ from lnst.Recipes.ENRT.IpsecEspAeadRecipe import IpsecEspAeadRecipe from lnst.Recipes.ENRT.IpsecEspAhCompRecipe import IpsecEspAhCompRecipe from lnst.Recipes.ENRT.NoVirtOvsVxlanRecipe import NoVirtOvsVxlanRecipe from lnst.Recipes.ENRT.OvS_DPDK_PvP import OvSDPDKPvPRecipe +from lnst.Recipes.ENRT.OvSDPDKBondRecipe import OvSDPDKBondRecipe from lnst.Recipes.ENRT.PingFloodRecipe import PingFloodRecipe from lnst.Recipes.ENRT.SimpleMacsecRecipe import SimpleMacsecRecipe from lnst.Recipes.ENRT.ShortLivedConnectionsRecipe import ShortLivedConnectionsRecipe -- 2.28.0 _______________________________________________ LNST-developers mailing list -- lnst-developers@lists.fedorahosted.org To unsubscribe send an email to lnst-developers-leave@lists.fedorahosted.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/lnst-developers@lists.fedorahos...
From: Jozef Urbanovsky jurbanov@redhat.com
Adding parameter for the forward-mode selection of the testPMD application running during the recipe. Branching is currently supporting only "mac" and "macswap" modes, where later needs the upstream DPDK to function properly. Therefore DPDK is built manually before the recipe run and requires "dpdk-testpmd" utility.
Signed-off-by: Jozef Urbanovsky jurbanov@redhat.com --- lnst/Tests/TestPMD.py | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-)
diff --git a/lnst/Tests/TestPMD.py b/lnst/Tests/TestPMD.py index a92a42a..dfb89ad 100644 --- a/lnst/Tests/TestPMD.py +++ b/lnst/Tests/TestPMD.py @@ -4,27 +4,43 @@ import signal from lnst.Common.Parameters import Param, StrParam, IntParam, FloatParam from lnst.Common.Parameters import IpParam, DeviceOrIpParam from lnst.Tests.BaseTestModule import BaseTestModule, TestModuleError +from lnst.Common.LnstError import LnstError +
class TestPMD(BaseTestModule): coremask = StrParam(mandatory=True) pmd_coremask = StrParam(mandatory=True)
- #TODO make ListParam + # TODO make ListParam + mode = StrParam(mandatory=True) nics = Param(mandatory=True) - peer_macs = Param(mandatory=True) + peer_macs = Param(mandatory=False)
def format_command(self): - testpmd_args = ["testpmd", - "-c", self.params.coremask, - "-n", "4", "--socket-mem", "1024,0"] - for nic in self.params.nics: - testpmd_args.extend(["-w", nic]) + if self.params.mode == "macswap": + testpmd_args = ["dpdk-testpmd", "--no-pci"] + else: + testpmd_args = ["testpmd"] + + testpmd_args.extend(["-c", self.params.coremask, + "-n", "4", "--socket-mem", "1024,0"]) + + for i, nic in enumerate(self.params.nics): + if self.params.mode == "mac": + testpmd_args.extend(["-w", nic]) + elif self.params.mode == "macswap": + testpmd_args.extend([f"--vdev=net_virtio_user{i+1},path=/var/run/openvswitch/{nic}"]) + else: + LnstError("Unsupported forward-mode parameter selected for the TestPMD.")
- testpmd_args.extend(["--", "-i", "--forward-mode", "mac", + testpmd_args.extend(["--", "-i", "--forward-mode", self.params.mode, "--coremask", self.params.pmd_coremask])
- for i, mac in enumerate(self.params.peer_macs): - testpmd_args.extend(["--eth-peer", "{},{}".format(i, mac)]) + if self.params.mode == "mac": + for i, mac in enumerate(self.params.peer_macs): + testpmd_args.extend(["--eth-peer", "{},{}".format(i, mac)]) + elif self.params.mode == "macswap": + testpmd_args.extend(["--port-topology=loop"])
return " ".join(testpmd_args)
Mon, Dec 14, 2020 at 11:59:27AM CET, jurbanov@redhat.com wrote:
From: Jozef Urbanovsky jurbanov@redhat.com
Adding parameter for the forward-mode selection of the testPMD application running during the recipe. Branching is currently supporting only "mac" and "macswap" modes, where later needs the upstream DPDK to function properly. Therefore DPDK is built manually before the recipe run and requires "dpdk-testpmd" utility.
If you're referring to something downstream, please remove it.
Signed-off-by: Jozef Urbanovsky jurbanov@redhat.com
lnst/Tests/TestPMD.py | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-)
diff --git a/lnst/Tests/TestPMD.py b/lnst/Tests/TestPMD.py index a92a42a..dfb89ad 100644 --- a/lnst/Tests/TestPMD.py +++ b/lnst/Tests/TestPMD.py @@ -4,27 +4,43 @@ import signal from lnst.Common.Parameters import Param, StrParam, IntParam, FloatParam from lnst.Common.Parameters import IpParam, DeviceOrIpParam from lnst.Tests.BaseTestModule import BaseTestModule, TestModuleError +from lnst.Common.LnstError import LnstError
class TestPMD(BaseTestModule): coremask = StrParam(mandatory=True) pmd_coremask = StrParam(mandatory=True)
- #TODO make ListParam
- # TODO make ListParam
- mode = StrParam(mandatory=True)
I'd rename this to forward_mode. The mode is too generic imo.
nics = Param(mandatory=True)
- peer_macs = Param(mandatory=True)
peer_macs = Param(mandatory=False)
def format_command(self):
testpmd_args = ["testpmd",
"-c", self.params.coremask,
"-n", "4", "--socket-mem", "1024,0"]
for nic in self.params.nics:
testpmd_args.extend(["-w", nic])
if self.params.mode == "macswap":
testpmd_args = ["dpdk-testpmd", "--no-pci"]
else:
testpmd_args = ["testpmd"]
testpmd_args.extend(["-c", self.params.coremask,
"-n", "4", "--socket-mem", "1024,0"])
for i, nic in enumerate(self.params.nics):
if self.params.mode == "mac":
testpmd_args.extend(["-w", nic])
elif self.params.mode == "macswap":
testpmd_args.extend([f"--vdev=net_virtio_user{i+1},path=/var/run/openvswitch/{nic}"])
else:
LnstError("Unsupported forward-mode parameter selected for the TestPMD.")
testpmd_args.extend(["--", "-i", "--forward-mode", "mac",
testpmd_args.extend(["--", "-i", "--forward-mode", self.params.mode, "--coremask", self.params.pmd_coremask])
for i, mac in enumerate(self.params.peer_macs):
testpmd_args.extend(["--eth-peer", "{},{}".format(i, mac)])
if self.params.mode == "mac":
for i, mac in enumerate(self.params.peer_macs):
testpmd_args.extend(["--eth-peer", "{},{}".format(i, mac)])
elif self.params.mode == "macswap":
testpmd_args.extend(["--port-topology=loop"]) return " ".join(testpmd_args)
-- 2.28.0 _______________________________________________ LNST-developers mailing list -- lnst-developers@lists.fedorahosted.org To unsubscribe send an email to lnst-developers-leave@lists.fedorahosted.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/lnst-developers@lists.fedorahos...
From: Jozef Urbanovsky jurbanov@redhat.com
Improvement to logs to be more human readable, especially in the Trex* flows.
Signed-off-by: Jozef Urbanovsky jurbanov@redhat.com --- lnst/Tests/TRex.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
diff --git a/lnst/Tests/TRex.py b/lnst/Tests/TRex.py index 40da393..4870b86 100644 --- a/lnst/Tests/TRex.py +++ b/lnst/Tests/TRex.py @@ -2,6 +2,7 @@ from lnst.Common.Parameters import Param, StrParam, IntParam, FloatParam from lnst.Common.Parameters import IpParam, DeviceOrIpParam from lnst.Tests.BaseTestModule import BaseTestModule, TestModuleError from lnst.External.TRex.TRexLib import TRexCli, TRexSrv, TRexError +from pprint import pformat
class TRexCommon(BaseTestModule): @@ -12,6 +13,8 @@ class TRexClient(TRexCommon):
flows = Param(mandatory=True)
+ module = StrParam(default="UDPSimple") + duration = IntParam(mandatory=True) warmup_time = IntParam(default=5)
@@ -24,6 +27,20 @@ class TRexClient(TRexCommon): super(TRexClient, self).__init__(**kwargs) self.impl = TRexCli(self.params)
+ def __repr__(self): + string = f""" + TrexClient( + trex_dir={self.impl.params.trex_dir}, + module={self.impl.params.module}, + msg_size={self.impl.params.msg_size}, + ports={self.impl.params.ports}, + server_hostname={self.impl.params.server_hostname}, + flows={pformat(self.impl.params.flows)} + ) + """ + + return string + def runtime_estimate(self): _duration_overhead = 5 return (self.params.duration + @@ -51,6 +68,16 @@ class TRexServer(TRexCommon): super(TRexServer, self).__init__(**kwargs) self.impl = TRexSrv(self.params)
+ def __repr__(self): + string = f""" + TrexServer(" + trex_dir={self.impl.params.trex_dir}, + cores={self.impl.params.cores}, + flows={pformat(self.impl.params.flows)} + ) + """ + return string + def run(self): self._res_data={} try:
On Mon, Dec 14, 2020 at 11:59:28AM +0100, jurbanov@redhat.com wrote:
From: Jozef Urbanovsky jurbanov@redhat.com
Improvement to logs to be more human readable, especially in the Trex* flows.
Signed-off-by: Jozef Urbanovsky jurbanov@redhat.com
lnst/Tests/TRex.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
diff --git a/lnst/Tests/TRex.py b/lnst/Tests/TRex.py index 40da393..4870b86 100644 --- a/lnst/Tests/TRex.py +++ b/lnst/Tests/TRex.py @@ -2,6 +2,7 @@ from lnst.Common.Parameters import Param, StrParam, IntParam, FloatParam from lnst.Common.Parameters import IpParam, DeviceOrIpParam from lnst.Tests.BaseTestModule import BaseTestModule, TestModuleError from lnst.External.TRex.TRexLib import TRexCli, TRexSrv, TRexError +from pprint import pformat
class TRexCommon(BaseTestModule): @@ -12,6 +13,8 @@ class TRexClient(TRexCommon):
flows = Param(mandatory=True)
- module = StrParam(default="UDPSimple")
- duration = IntParam(mandatory=True) warmup_time = IntParam(default=5)
@@ -24,6 +27,20 @@ class TRexClient(TRexCommon): super(TRexClient, self).__init__(**kwargs) self.impl = TRexCli(self.params)
- def __repr__(self):
string = f"""
TrexClient(
trex_dir={self.impl.params.trex_dir},
module={self.impl.params.module},
msg_size={self.impl.params.msg_size},
ports={self.impl.params.ports},
server_hostname={self.impl.params.server_hostname},
flows={pformat(self.impl.params.flows)}
)
"""
return string
- def runtime_estimate(self): _duration_overhead = 5 return (self.params.duration +
@@ -51,6 +68,16 @@ class TRexServer(TRexCommon): super(TRexServer, self).__init__(**kwargs) self.impl = TRexSrv(self.params)
- def __repr__(self):
string = f"""
TrexServer("
^
I think there's an extra " character? Possibly a typo.
-Ondrej
trex_dir={self.impl.params.trex_dir},
cores={self.impl.params.cores},
flows={pformat(self.impl.params.flows)}
)
"""
return string
- def run(self): self._res_data={} try:
-- 2.28.0 _______________________________________________ LNST-developers mailing list -- lnst-developers@lists.fedorahosted.org To unsubscribe send an email to lnst-developers-leave@lists.fedorahosted.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/lnst-developers@lists.fedorahos...
From: Jozef Urbanovsky jurbanov@redhat.com
Expose module through the flow type. Fix version_job call. TRex server needs longer to start with specific configuration, thus increasing the time we wait until it is started
Signed-off-by: Jozef Urbanovsky jurbanov@redhat.com --- lnst/RecipeCommon/Perf/Measurements/TRexFlowMeasurement.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/lnst/RecipeCommon/Perf/Measurements/TRexFlowMeasurement.py b/lnst/RecipeCommon/Perf/Measurements/TRexFlowMeasurement.py index c12e922..71c0e8c 100644 --- a/lnst/RecipeCommon/Perf/Measurements/TRexFlowMeasurement.py +++ b/lnst/RecipeCommon/Perf/Measurements/TRexFlowMeasurement.py @@ -48,7 +48,7 @@ class TRexFlowMeasurement(BaseFlowMeasurement): "hosts_trex_versions": self._hosts_versions}
def _get_host_trex_version(self, host): - version_job = host.run("cd {trex_dir} ; ./t-rex-64 --help", job_level = ResultLevel.DEBUG) + version_job = host.run(f"cd {self._trex_dir} ; ./t-rex-64 --help", job_level = ResultLevel.DEBUG) if version_job.passed: match = re.match(r"Starting TRex (v.+?) please wait ...", version_job.stdout) if match: @@ -66,7 +66,7 @@ class TRexFlowMeasurement(BaseFlowMeasurement): test.server_job.start(bg=True)
#wait for Trex server to start - time.sleep(5) + time.sleep(15)
for test in tests: test.client_job.start(bg=True) @@ -107,6 +107,7 @@ class TRexFlowMeasurement(BaseFlowMeasurement): trex_dir=self._trex_dir, ports=list(range(len(flow_tuples))), flows=flow_tuples, + module=flows[0].type, duration=flows[0].duration, msg_size=flows[0].msg_size))
From: Jozef Urbanovsky jurbanov@redhat.com
Dataclass package is required for the new OvSDPDKBondRecipe, which is not present in Python3.6 and below.
Signed-off-by: Jozef Urbanovsky jurbanov@redhat.com --- requirements.txt | 1 + 1 file changed, 1 insertion(+)
diff --git a/requirements.txt b/requirements.txt index bd4a913..5a41138 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ lxml pyroute2 libvirt-python ethtool +dataclasses
From: Jozef Urbanovsky jurbanov@redhat.com
New mixins dedicated to apply test tweaks were designed in mind with the iperf measurement tool. For Trex, that is being used for the DPDK mostly, these tweaks do not apply, as well as, have a little different data structure that collides with current implementation. Therefore, we are overriding these methods to do nothing.
Signed-off-by: Jozef Urbanovsky jurbanov@redhat.com --- lnst/Recipes/ENRT/OvSDPDKBondRecipe.py | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/lnst/Recipes/ENRT/OvSDPDKBondRecipe.py b/lnst/Recipes/ENRT/OvSDPDKBondRecipe.py index 7e9a4cb..4c1af09 100644 --- a/lnst/Recipes/ENRT/OvSDPDKBondRecipe.py +++ b/lnst/Recipes/ENRT/OvSDPDKBondRecipe.py @@ -246,3 +246,12 @@ class OvSDPDKBondRecipe(CommonHWSubConfigMixin, BaseEnrtRecipe):
def generate_perf_endpoints(self, config): return [(self.matched.host1.dummy_cfg, self.matched.host2.dummy_cfg)] + + def apply_perf_test_tweak(self, config): + pass + + def describe_perf_test_tweak(self, config): + pass + + def remove_perf_test_tweak(self, config): + pass \ No newline at end of file
Mon, Dec 14, 2020 at 11:59:31AM CET, jurbanov@redhat.com wrote:
From: Jozef Urbanovsky jurbanov@redhat.com
New mixins dedicated to apply test tweaks were designed in mind with the iperf measurement tool. For Trex, that is being used for the DPDK mostly, these tweaks do not apply, as well as, have a little different data structure that collides with current implementation. Therefore, we are overriding these methods to do nothing.
Signed-off-by: Jozef Urbanovsky jurbanov@redhat.com
lnst/Recipes/ENRT/OvSDPDKBondRecipe.py | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/lnst/Recipes/ENRT/OvSDPDKBondRecipe.py b/lnst/Recipes/ENRT/OvSDPDKBondRecipe.py index 7e9a4cb..4c1af09 100644 --- a/lnst/Recipes/ENRT/OvSDPDKBondRecipe.py +++ b/lnst/Recipes/ENRT/OvSDPDKBondRecipe.py @@ -246,3 +246,12 @@ class OvSDPDKBondRecipe(CommonHWSubConfigMixin, BaseEnrtRecipe):
def generate_perf_endpoints(self, config): return [(self.matched.host1.dummy_cfg, self.matched.host2.dummy_cfg)]
- def apply_perf_test_tweak(self, config):
pass
- def describe_perf_test_tweak(self, config):
pass
- def remove_perf_test_tweak(self, config):
pass
\ No newline at end of file
^^^ newline warning.
-- 2.28.0 _______________________________________________ LNST-developers mailing list -- lnst-developers@lists.fedorahosted.org To unsubscribe send an email to lnst-developers-leave@lists.fedorahosted.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/lnst-developers@lists.fedorahos...
On Mon, Dec 14, 2020 at 11:59:25AM +0100, jurbanov@redhat.com wrote:
From: Jozef Urbanovsky jurbanov@redhat.com
Hi,
This patchset adds OvSDPDKBondRecipe and fixes some issues with test tools required for the recipe. Patchset has been reviewed in internal downstream, before it was decided to split it to upstream and downstream.
It has been tested to be fully functional.
Jozef Urbanovsky (6): lnst.Recipes.ENRT.OvSDPDKBondRecipe: add new recipe lnst.Tests.TestPMD: add mode branching lnst.Tests.TRex: add __repr__ methods, expose module parameter lnst.RecipeCommon.Perf.Measurements.TRexFlowMeasurement: fixes requirements: add dataclasses package lnst.Recipes.ENRT.OvSDPDKBondRecipe: override *test_tweak methods
.../Perf/Measurements/TRexFlowMeasurement.py | 5 +- lnst/Recipes/ENRT/OvSDPDKBondRecipe.py | 257 ++++++++++++++++++ lnst/Recipes/ENRT/__init__.py | 1 + lnst/Tests/TRex.py | 27 ++ lnst/Tests/TestPMD.py | 36 ++- requirements.txt | 1 + 6 files changed, 315 insertions(+), 12 deletions(-) create mode 100644 lnst/Recipes/ENRT/OvSDPDKBondRecipe.py
-- 2.28.0 _______________________________________________ LNST-developers mailing list -- lnst-developers@lists.fedorahosted.org To unsubscribe send an email to lnst-developers-leave@lists.fedorahosted.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/lnst-developers@lists.fedorahos...
Other than my one comment about the extra character, I think the patchset looks sane, please fix the minor cosmetic issues as pointed out by Jan and the one extra character and I'll push this to master.
-Ondrej
lnst-developers@lists.fedorahosted.org