Mon, May 31, 2021 at 02:39:25PM CEST, olichtne(a)redhat.com wrote:
On Thu, May 27, 2021 at 02:04:21PM +0200, Jan Tluka wrote:
> Signed-off-by: Jan Tluka <jtluka(a)redhat.com>
> ---
> docs/source/gre_lwt_tunnel_recipe.rst | 6 +
> docs/source/specific_scenarios.rst | 1 +
> lnst/Recipes/ENRT/GreLwtTunnelRecipe.py | 233 ++++++++++++++++++++++++
> lnst/Recipes/ENRT/__init__.py | 1 +
> 4 files changed, 241 insertions(+)
> create mode 100644 docs/source/gre_lwt_tunnel_recipe.rst
> create mode 100644 lnst/Recipes/ENRT/GreLwtTunnelRecipe.py
>
> diff --git a/docs/source/gre_lwt_tunnel_recipe.rst
b/docs/source/gre_lwt_tunnel_recipe.rst
> new file mode 100644
> index 00000000..6a3d63e4
> --- /dev/null
> +++ b/docs/source/gre_lwt_tunnel_recipe.rst
> @@ -0,0 +1,6 @@
> +GreLwtTunnelRecipe
> +^^^^^^^^^^^^^^^^^^^
> +
> +.. autoclass:: lnst.Recipes.ENRT.GreLwtTunnelRecipe.GreLwtTunnelRecipe
> + :members:
> + :show-inheritance:
> diff --git a/docs/source/specific_scenarios.rst b/docs/source/specific_scenarios.rst
> index 4b952d48..01459da1 100644
> --- a/docs/source/specific_scenarios.rst
> +++ b/docs/source/specific_scenarios.rst
> @@ -8,6 +8,7 @@ Specific ENRT scenarios
> vlans_recipe
> vlans_over_bond_recipe
> gre_tunnel_recipe
> + gre_lwt_tunnel_recipe
> gre_tunnel_over_bond_recipe
> ip6gre_tunnel_recipe
> ip6gre_netns_tunnel_recipe
> diff --git a/lnst/Recipes/ENRT/GreLwtTunnelRecipe.py
b/lnst/Recipes/ENRT/GreLwtTunnelRecipe.py
> new file mode 100644
> index 00000000..365c9f74
> --- /dev/null
> +++ b/lnst/Recipes/ENRT/GreLwtTunnelRecipe.py
> @@ -0,0 +1,233 @@
> +from lnst.Controller import HostReq, DeviceReq, RecipeParam
> +from lnst.Common.IpAddress import (
> + AF_INET,
> + AF_INET6,
> + ipaddress,
> + Ip4Address,
> + Ip6Address,
> +)
> +from lnst.Devices import GreDevice, LoopbackDevice
> +from lnst.RecipeCommon.Ping.PingEndpoints import PingEndpoints
> +from lnst.RecipeCommon.PacketAssert import PacketAssertConf
> +from lnst.Common.Parameters import Param, StrParam, ChoiceParam
> +from lnst.Recipes.ENRT.BaseTunnelRecipe import BaseTunnelRecipe
> +from lnst.Recipes.ENRT.ConfigMixins.OffloadSubConfigMixin import (
> + OffloadSubConfigMixin,
> +)
> +from lnst.Recipes.ENRT.ConfigMixins.PauseFramesHWConfigMixin import (
> + PauseFramesHWConfigMixin,
> +)
> +
> +
> +class GreLwtTunnelRecipe(
> + PauseFramesHWConfigMixin, OffloadSubConfigMixin, BaseTunnelRecipe
> +):
> + """
> + This class implements a recipe that configures a simple Gre lightweight
> + tunnel between two hosts.
> +
> + .. code-block:: none
> +
> + .--------.
> + .------| switch |-----.
> + | '--------' |
> + | |
> + .-------|------. .-------|------.
> + | .--'-. | | .--'-. |
> + | |eth0| | | |eth0| |
> + | '----' | | '----' |
> + | | | | | | | |
> + | ----' '--- | | ----' '--- |
> + | gre tunnel | | gre 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 carrier_ipversion:
> + This parameter specifies whether IPv4 or IPv6 addresses are
> + used for the underlying (carrier) network. The value is either
> + **ipv4** or **ipv6**
> + """
> +
> + host1 = HostReq()
> + host1.eth0 = DeviceReq(label="net1",
driver=RecipeParam("driver"))
> +
> + host2 = HostReq()
> + host2.eth0 = DeviceReq(label="net1",
driver=RecipeParam("driver"))
> +
> + offload_combinations = Param(
> + default=(
> + dict(gro="on", gso="on", tso="on"),
> + dict(gro="off", gso="on", tso="on"),
> + dict(gro="on", gso="off", tso="off"),
> + dict(gro="on", gso="on", tso="off"),
> + )
> + )
> +
> + # TODO: ping over IPv6 does not work yet
Because of an issue with the configuration or because the device/tunnel
doesn't support it?
-Ondrej
Generally because of the test configuration. But it seems that there's
probably a generic issue with how the IPv6 works, but I'm not 100% sure.
-Jan
> + ip_versions = Param(default=("ipv4",))
> + carrier_ipversion = ChoiceParam(type=StrParam, choices=set(["ipv4",
"ipv6"]))
> +
> + 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]):
> + if self.params.carrier_ipversion == "ipv4":
> + device.ip_add(ipaddress("192.168.101." + str(i + 1) +
"/24"))
> + else:
> + device.ip_add(ipaddress("fc00::" + str(i + 1) +
"/64"))
> + device.up()
> + configuration.test_wide_devices.append(device)
> +
> + self.wait_tentative_ips(configuration.test_wide_devices)
> + configuration.tunnel_endpoints = (host1.eth0, host2.eth0)
> +
> + def create_tunnel(self, configuration):
> + """
> + The Gre tunnel devices are created with external flag specified
> + so that the encapsulation can be defined externally by routes.
> +
> + Routes for IPv4 and IPv6 networks to be tunneled through the Gre are
> + added.
> +
> + IPv4 and IPv6 addresses of the tunneled networks are configured on
> + the loopback devices of the matched hosts.
> + """
> + endpoint1, endpoint2 = configuration.tunnel_endpoints
> + m1 = endpoint1.netns
> + m2 = endpoint2.netns
> + if self.params.carrier_ipversion == "ipv4":
> + ip_filter = {"family": AF_INET}
> + else:
> + ip_filter = {"family": AF_INET6, "is_link_local":
False}
> +
> + endpoint1_ip = endpoint1.ips_filter(**ip_filter)[0]
> + endpoint2_ip = endpoint2.ips_filter(**ip_filter)[0]
> +
> + m1_dummy_ip = ipaddress("172.16.10.1/32")
> + m1_dummy_ip6 = ipaddress("fc00:a::1/128")
> + m2_dummy_ip = ipaddress("172.16.20.1/32")
> + m2_dummy_ip6 = ipaddress("fc00:b::1/128")
> +
> + m1.gre_tunnel = GreDevice(external=True)
> + m2.gre_tunnel = GreDevice(external=True)
> + m1.lo = LoopbackDevice()
> + m2.lo = LoopbackDevice()
> +
> + # A
> + m1.lo.ip_add(m1_dummy_ip)
> + m1.lo.ip_add(m1_dummy_ip6)
> + m1.gre_tunnel.mtu = 1400
> + m1.gre_tunnel.up()
> +
> + # B
> + m2.lo.ip_add(m2_dummy_ip)
> + m2.lo.ip_add(m2_dummy_ip6)
> + m2.gre_tunnel.mtu = 1400
> + m2.gre_tunnel.up()
> +
> + tunnel_id = 1234
> + encap = "ip" if self.params.carrier_ipversion == "ipv4"
else "ip6"
> + m1.run(
> + "ip route add {} encap {} id {} dst {} dev {}".format(
> + m2_dummy_ip, encap, tunnel_id, endpoint2_ip, m1.gre_tunnel.name
> + )
> + )
> + m2.run(
> + "ip route add {} encap {} id {} dst {} dev {}".format(
> + m1_dummy_ip, encap, tunnel_id, endpoint1_ip, m2.gre_tunnel.name
> + )
> + )
> + m1.run(
> + "ip route add {} encap {} id {} dst {} dev {}".format(
> + m2_dummy_ip6, encap, tunnel_id, endpoint2_ip, m1.gre_tunnel.name
> + )
> + )
> + m2.run(
> + "ip route add {} encap {} id {} dst {} dev {}".format(
> + m1_dummy_ip6, encap, tunnel_id, endpoint1_ip, m2.gre_tunnel.name
> + )
> + )
> +
> + configuration.tunnel_devices.extend([m1.gre_tunnel, m2.gre_tunnel])
> + self.wait_tentative_ips([m1.lo, m2.lo])
> +
> + def generate_ping_endpoints(self, config):
> + """
> + The ping endpoints for this recipe are the loopback devices that
> + are configured with IP addresses of the tunnelled networks.
> +
> + Returned as::
> +
> + [PingEndpoints(self.matched.host1.lo, self.matched.host2.lo)]
> + """
> + return [PingEndpoints(self.matched.host1.lo, self.matched.host2.lo)]
> +
> + def get_packet_assert_config(self, ping_config):
> + """
> + The packet assert test configuration contains filter for gre protocol
> + and grep patterns to match the ICMP or ICMP6 echo requests encapsulated
> + by Gre.
> + """
> + if self.params.carrier_ipversion == "ipv4":
> + ip_filter = {"family": AF_INET}
> + else:
> + 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"] = "proto gre"
> +
> + if isinstance(ip2, Ip4Address):
> + pat1 = "{} > {}: GREv0, .* IP {} > {}: ICMP echo
request".format(
> + m1_carrier_ip, m2_carrier_ip, ip1, ip2
> + )
> + pat2 = "{} > {}: GREv0 \| {} > {}: ICMP echo
request".format(
> + m1_carrier_ip, m2_carrier_ip, ip1, ip2
> + )
> + grep_pattern = ["({})|({})".format(pat1, pat2)]
> + elif isinstance(ip2, Ip6Address):
> + pat1 = "{} > {}: GREv0, .* IP6 {} > {}: ICMP6, echo
request".format(
> + m1_carrier_ip, m2_carrier_ip, ip1, ip2
> + )
> + pat2 = "{} > {}: GREv0 \| {} > {}: ICMP6, echo
request".format(
> + m1_carrier_ip, m2_carrier_ip, ip1, ip2
> + )
> + grep_pattern = ["({})|({})".format(pat1, pat2)]
> + else:
> + raise Exception("The destination address is nor IPv4 or IPv6
address")
> +
> + 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
> +
> + @property
> + def offload_nics(self):
> + return [self.matched.host1.eth0, self.matched.host2.eth0]
> +
> + @property
> + def pause_frames_dev_list(self):
> + return [self.matched.host1.eth0, self.matched.host2.eth0]
> diff --git a/lnst/Recipes/ENRT/__init__.py b/lnst/Recipes/ENRT/__init__.py
> index eb91b4c8..454ab296 100644
> --- a/lnst/Recipes/ENRT/__init__.py
> +++ b/lnst/Recipes/ENRT/__init__.py
> @@ -82,6 +82,7 @@ from lnst.Recipes.ENRT.VxlanMulticastRecipe import
VxlanMulticastRecipe
> from lnst.Recipes.ENRT.VxlanRemoteRecipe import VxlanRemoteRecipe
> from lnst.Recipes.ENRT.GreTunnelRecipe import GreTunnelRecipe
> from lnst.Recipes.ENRT.GreTunnelOverBondRecipe import GreTunnelOverBondRecipe
> +from lnst.Recipes.ENRT.GreLwtTunnelRecipe import GreLwtTunnelRecipe
> from lnst.Recipes.ENRT.Ip6GreTunnelRecipe import Ip6GreTunnelRecipe
> from lnst.Recipes.ENRT.Ip6GreNetnsTunnelRecipe import Ip6GreNetnsTunnelRecipe
> from lnst.Recipes.ENRT.SitTunnelRecipe import SitTunnelRecipe
> --
> 2.26.3
> _______________________________________________
> LNST-developers mailing list -- lnst-developers(a)lists.fedorahosted.org
> To unsubscribe send an email to lnst-developers-leave(a)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.fedora...
> Do not reply to spam on the list, report it:
https://pagure.io/fedora-infrastructure