From: Ondrej Lichtner <olichtne(a)redhat.com>
The OffloadSubConfigMixin is an EnrtBaseRecipe subconfiguration mixin
class implementing the offload subconfiguration looping. This includes
generating, applying, removing and describing the subconfiguration.
It also includes overriding the default perf test flow generation loop
so that certain test configurations are ignored when certain offloads
are configured.
Enabling this mixin for the SimplePerfRecipe means simply adding it as a
base class and defining the required property 'offload_nics' indicating
which devices should the offload configuration be done for.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
.../ConfigMixins/OffloadSubConfigMixin.py | 103 ++++++++++++++++++
lnst/Recipes/ENRT/SimplePerfRecipe.py | 13 ++-
2 files changed, 115 insertions(+), 1 deletion(-)
create mode 100644 lnst/Recipes/ENRT/ConfigMixins/OffloadSubConfigMixin.py
diff --git a/lnst/Recipes/ENRT/ConfigMixins/OffloadSubConfigMixin.py
b/lnst/Recipes/ENRT/ConfigMixins/OffloadSubConfigMixin.py
new file mode 100644
index 0000000..f50a165
--- /dev/null
+++ b/lnst/Recipes/ENRT/ConfigMixins/OffloadSubConfigMixin.py
@@ -0,0 +1,103 @@
+import copy
+
+from lnst.Common.Parameters import Param
+from lnst.Controller.RecipeResults import ResultLevel
+from lnst.Recipes.ENRT.ConfigMixins.BaseSubConfigMixin import BaseSubConfigMixin
+
+
+class OffloadSubConfigMixin(BaseSubConfigMixin):
+ offload_combinations = Param(
+ default=(dict(gro="on", gso="on", tso="on",
tx="on", rx="on"),)
+ )
+
+ @property
+ def offload_nics(self):
+ raise NotImplementedError("Subclass must implement this property")
+
+ def generate_sub_configurations(self, config):
+ for parent_config in super().generate_sub_configurations(config):
+ for offload_settings in self.params.offload_combinations:
+ new_config = copy.copy(config)
+ new_config.offload_settings = offload_settings
+
+ yield new_config
+
+ def apply_sub_configuration(self, config):
+ super().apply_sub_configuration(config)
+
+ offload_settings = getattr(config, "offload_settings", None)
+ if offload_settings:
+ ethtool_offload_string = ""
+ for name, value in list(offload_settings.items()):
+ ethtool_offload_string += " %s %s" % (name, value)
+
+ for nic in self.offload_nics:
+ if "sctp_stream" in self.params.perf_tests:
+ nic.netns.run(
+ "iptables -I OUTPUT ! -o %s -p sctp -j DROP" %
nic.name,
+ job_level=ResultLevel.NORMAL,
+ )
+
+ nic.netns.run(
+ "ethtool -K {} {}".format(nic.name,
ethtool_offload_string),
+ job_level=ResultLevel.NORMAL,
+ )
+
+ def generate_sub_configuration_description(self, config):
+ description = super().generate_sub_configuration_description(config)
+ description.append(
+ "Currently configured offload combination: {}".format(
+ " ".join(
+ [
+ "{}={}".format(k, v)
+ for k, v in config.offload_settings.items()
+ ]
+ )
+ )
+ )
+ return description
+
+ def remove_sub_configuration(self, config):
+ offload_settings = getattr(config, "offload_settings", None)
+ if offload_settings:
+ ethtool_offload_string = ""
+ for name, value in list(offload_settings.items()):
+ ethtool_offload_string += " %s %s" % (name, "on")
+
+ for nic in self.offload_nics:
+ if "sctp_stream" in self.params.perf_tests:
+ nic.netns.run(
+ "iptables -D OUTPUT ! -o %s -p sctp -j DROP" %
nic.name,
+ job_level=ResultLevel.NORMAL,
+ )
+
+ # set all the offloads back to 'on' state
+ nic.netns.run(
+ "ethtool -K {} {}".format(nic.name,
ethtool_offload_string),
+ job_level=ResultLevel.NORMAL,
+ )
+
+ return super().remove_sub_configuration(config)
+
+ def generate_flow_combinations(self, config):
+ for flows in super().generate_flow_combinations(config):
+ if self._check_test_offload_conflicts(config, flows):
+ # TODO log skip
+ continue
+ else:
+ yield flows
+
+ def _check_test_offload_conflicts(self, config, flows):
+ for flow in flows:
+ if (
+ flow.type == "udp_stream"
+ and config.offload_settings.get("gro", "on") ==
"off"
+ ):
+ return True
+ elif (
+ flow.type == "sctp_stream"
+ and "off" in config.offload_settings.values()
+ and config.offload_settings.get("gso", "on") ==
"on"
+ ):
+ return True
+ return False
diff --git a/lnst/Recipes/ENRT/SimplePerfRecipe.py
b/lnst/Recipes/ENRT/SimplePerfRecipe.py
index d558bea..b5414c8 100644
--- a/lnst/Recipes/ENRT/SimplePerfRecipe.py
+++ b/lnst/Recipes/ENRT/SimplePerfRecipe.py
@@ -6,7 +6,14 @@
from lnst.Recipes.ENRT.BaseEnrtRecipe import BaseEnrtRecipe
-class SimplePerfRecipe(BaseEnrtRecipe):
+from lnst.Recipes.ENRT.ConfigMixins.OffloadSubConfigMixin import (
+ OffloadSubConfigMixin,
+)
+
+
+class SimplePerfRecipe(
+ OffloadSubConfigMixin, BaseEnrtRecipe
+):
host1 = HostReq()
host1.eth0 = DeviceReq(label="net1",
driver=RecipeParam("driver"))
@@ -72,3 +79,7 @@ def generate_ping_endpoints(self, config):
def generate_perf_endpoints(self, config):
return [(self.matched.host1.eth0, self.matched.host2.eth0)]
+
+ @property
+ def offload_nics(self):
+ return [self.matched.host1.eth0, self.matched.host2.eth0]
--
2.22.0