Signed-off-by: Jan Tluka <jtluka(a)redhat.com>
---
docs/source/ip6tnl_tunnel_recipe.rst | 6 +
docs/source/specific_scenarios.rst | 1 +
lnst/Recipes/ENRT/Ip6TnlTunnelRecipe.py | 154 ++++++++++++++++++++++++
lnst/Recipes/ENRT/__init__.py | 1 +
4 files changed, 162 insertions(+)
create mode 100644 docs/source/ip6tnl_tunnel_recipe.rst
create mode 100644 lnst/Recipes/ENRT/Ip6TnlTunnelRecipe.py
diff --git a/docs/source/ip6tnl_tunnel_recipe.rst b/docs/source/ip6tnl_tunnel_recipe.rst
new file mode 100644
index 00000000..e3d57d68
--- /dev/null
+++ b/docs/source/ip6tnl_tunnel_recipe.rst
@@ -0,0 +1,6 @@
+Ip6TnlTunnelRecipe
+^^^^^^^^^^^^^^^^^^^
+
+.. autoclass:: lnst.Recipes.ENRT.Ip6TnlTunnelRecipe.Ip6TnlTunnelRecipe
+ :members:
+ :show-inheritance:
diff --git a/docs/source/specific_scenarios.rst b/docs/source/specific_scenarios.rst
index fb515246..0e56c335 100644
--- a/docs/source/specific_scenarios.rst
+++ b/docs/source/specific_scenarios.rst
@@ -12,4 +12,5 @@ Specific ENRT scenarios
ip6gre_tunnel_recipe
sit_tunnel_recipe
ipip_tunnel_recipe
+ ip6tnl_tunnel_recipe
l2tp_tunnel_recipe
diff --git a/lnst/Recipes/ENRT/Ip6TnlTunnelRecipe.py
b/lnst/Recipes/ENRT/Ip6TnlTunnelRecipe.py
new file mode 100644
index 00000000..eaa9cba4
--- /dev/null
+++ b/lnst/Recipes/ENRT/Ip6TnlTunnelRecipe.py
@@ -0,0 +1,154 @@
+from lnst.Controller import HostReq, DeviceReq, RecipeParam
+from lnst.Common.IpAddress import (
+ AF_INET6,
+ ipaddress,
+)
+from lnst.Devices import Ip6TnlDevice
+from lnst.RecipeCommon.Ping.PingEndpoints import PingEndpoints
+from lnst.RecipeCommon.PacketAssert import PacketAssertConf
+from lnst.Common.Parameters import StrParam, ChoiceParam
+from lnst.Recipes.ENRT.BaseTunnelRecipe import BaseTunnelRecipe
+
+
+class Ip6TnlTunnelRecipe(BaseTunnelRecipe):
+ """
+ This class implements a recipe that configures a simple Ip6Tnl tunnel between
+ two hosts.
+
+ .. code-block:: none
+
+ .--------.
+ .------| switch |-----.
+ | '--------' |
+ | |
+ .-------|------. .-------|------.
+ | .--'-. | | .--'-. |
+ | |eth0| | | |eth0| |
+ | '----' | | '----' |
+ | | | | | | | |
+ | ----' '--- | | ----' '--- |
+ | ip6tnl tunnel| | ip6tnl tunnel|
+ | ---------- | | ---------- |
+ | | | |
+ | host1 | | host2 |
+ '--------------' '--------------'
+
+ The actual test machinery is implemented in the :any:`BaseEnrtRecipe` class.
+
+ The test wide configuration is implemented in the :any:`BaseTunnelRecipe`
+ class.
+
+ The recipe provides additional parameter:
+
+ :param tunnel_mode:
+ this parameter specifies the mode of the ip6tnl tunnel, can be any
+ of the **any**, **ipip6** or **ip6ip6**
+ """
+
+ host1 = HostReq()
+ host1.eth0 = DeviceReq(label="net1",
driver=RecipeParam("driver"))
+
+ host2 = HostReq()
+ host2.eth0 = DeviceReq(label="net1",
driver=RecipeParam("driver"))
+
+ tunnel_mode = ChoiceParam(
+ type=StrParam, choices=set(["any", "ipip6",
"ip6ip6"]), mandatory=True
+ )
+
+ def configure_underlying_network(self, configuration):
+ """
+ The underlying network for the tunnel consists of the Ethernet
+ devices on the matched hosts.
+ """
+ host1, host2 = self.matched.host1, self.matched.host2
+ for i, device in enumerate([host1.eth0, host2.eth0]):
+ device.ip_add(ipaddress("fc00::" + str(i + 1) + "/64"))
+ device.up()
+ configuration.test_wide_devices.append(device)
+
+ configuration.tunnel_endpoints = (host1.eth0, host2.eth0)
+
+ def create_tunnel(self, configuration):
+ """
+ The ip6tnl tunnel devices are configured with IPv6 addresses.
+ """
+ endpoint1, endpoint2 = configuration.tunnel_endpoints
+ m1 = endpoint1.netns
+ m2 = endpoint2.netns
+ ip_filter = {"family": AF_INET6}
+ endpoint1_ip = endpoint1.ips_filter(**ip_filter)[0]
+ endpoint2_ip = endpoint2.ips_filter(**ip_filter)[0]
+
+ a_ip6 = ipaddress("3001:db8:ac10:fe01::2/64")
+ b_ip6 = ipaddress("3001:db8:ac10:fe01::3/64")
+
+ m1.ip6tnl = Ip6TnlDevice(
+ local=endpoint1_ip,
+ remote=endpoint2_ip,
+ mode=self.params.tunnel_mode,
+ ttl=64,
+ )
+ m2.ip6tnl = Ip6TnlDevice(
+ local=endpoint2_ip,
+ remote=endpoint1_ip,
+ mode=self.params.tunnel_mode,
+ ttl=64,
+ )
+
+ # A
+ m1.ip6tnl.up()
+ m1.ip6tnl.ip_add(a_ip6)
+
+ # B
+ m2.ip6tnl.up()
+ m2.ip6tnl.ip_add(b_ip6)
+
+ configuration.tunnel_devices.extend([m1.ip6tnl, m2.ip6tnl])
+ self.wait_tentative_ips(configuration.tunnel_devices)
+
+ def generate_ping_endpoints(self, config):
+ """
+ The ping endpoints for this recipe are simply the tunnel endpoints
+
+ Returned as::
+
+ [PingEndpoints(self.matched.host1.ip6tnl, self.matched.host2.ip6tnl)]
+ """
+ return [
+ PingEndpoints(
+ self.matched.host1.ip6tnl, self.matched.host2.ip6tnl
+ )
+ ]
+
+ def get_packet_assert_config(self, ping_config):
+ """
+ The packet assert test configuration contains filter for ip6 protocol
+ and grep patterns to match the ICMP6 echo requests encapsulated
+ by Ip6Tnl.
+ """
+ ip_filter = {"family": AF_INET6, "is_link_local": False}
+ m1_carrier = self.matched.host1.eth0
+ m2_carrier = self.matched.host2.eth0
+ m1_carrier_ip = m1_carrier.ips_filter(**ip_filter)[0]
+ m2_carrier_ip = m2_carrier.ips_filter(**ip_filter)[0]
+
+ ip1 = ping_config.client_bind
+ ip2 = ping_config.destination_address
+
+ pa_kwargs = {}
+ pa_kwargs["p_filter"] = "ip6"
+
+ grep_pattern = [
+ "IP6 {} > {}: DSTOPT IP6 {} > {}: ICMP6".format(
+ m1_carrier_ip, m2_carrier_ip, ip1, ip2
+ )
+ ]
+
+ pa_kwargs["grep_for"] = grep_pattern
+
+ if ping_config.count:
+ pa_kwargs["p_min"] = ping_config.count
+ m2 = ping_config.destination
+ pa_config = PacketAssertConf(m2, m2_carrier, **pa_kwargs)
+
+ return pa_config
diff --git a/lnst/Recipes/ENRT/__init__.py b/lnst/Recipes/ENRT/__init__.py
index 81faee7c..8de93e25 100644
--- a/lnst/Recipes/ENRT/__init__.py
+++ b/lnst/Recipes/ENRT/__init__.py
@@ -85,6 +85,7 @@ from lnst.Recipes.ENRT.GreTunnelOverBondRecipe import
GreTunnelOverBondRecipe
from lnst.Recipes.ENRT.Ip6GreTunnelRecipe import Ip6GreTunnelRecipe
from lnst.Recipes.ENRT.SitTunnelRecipe import SitTunnelRecipe
from lnst.Recipes.ENRT.IpIpTunnelRecipe import IpIpTunnelRecipe
+from lnst.Recipes.ENRT.Ip6TnlTunnelRecipe import Ip6TnlTunnelRecipe
from lnst.Recipes.ENRT.BaseEnrtRecipe import BaseEnrtRecipe
from lnst.Recipes.ENRT.BaseTunnelRecipe import BaseTunnelRecipe
--
2.26.3