From 20ecb6d4ccaf903bcaaf658b1a655dd8d79b989c Mon Sep 17 00:00:00 2001 From: Viacheslav Hletenko Date: Wed, 22 Jan 2025 15:01:05 +0000 Subject: [PATCH] GRE: Add tunnel-type erspan, l3 and teb Add tunnel type - erspan - l3 - teb (Transparent Ethernet Bridge) By default L3 GRE interfaces cannot be bridged to a bridge interface. Add the ability to change tunnel type. set vpp interfaces gre gre2 tunnel-type 'teb' --- interface-definitions/vpp.xml.in | 25 ++++++++++++++++ python/vyos/vpp/interface/gre.py | 45 +++++++++++++++++++++++++++-- smoketest/scripts/cli/test_vpp.py | 4 +-- src/conf_mode/vpp_interfaces_gre.py | 5 ++-- 4 files changed, 72 insertions(+), 7 deletions(-) diff --git a/interface-definitions/vpp.xml.in b/interface-definitions/vpp.xml.in index 0718ba0..c946839 100644 --- a/interface-definitions/vpp.xml.in +++ b/interface-definitions/vpp.xml.in @@ -180,6 +180,31 @@ + + + GRE tunnel type + + erspan l3 teb + + + erspan + Encapsulated Remote Switched Port Analyzer + + + l3 + Generic Routing Encapsulation (network layer) + + + teb + L2 Transparent Ethernet Bridge + + + (erspan|l3|teb) + + Invalid encapsulation, must be one of: l3, teb or erspan + + l3 + #include #include #include diff --git a/python/vyos/vpp/interface/gre.py b/python/vyos/vpp/interface/gre.py index 20a7ae9..65559f2 100644 --- a/python/vyos/vpp/interface/gre.py +++ b/python/vyos/vpp/interface/gre.py @@ -30,20 +30,58 @@ def show(): class GREInterface: - def __init__(self, ifname, source_address, remote, kernel_interface: str = ''): + """ + Class representing a GRE (Generic Routing Encapsulation) interface. + + Attributes: + ifname (str): The interface name. + source_address (str): The source IP address for the GRE tunnel. + remote (str): The remote IP address for the GRE tunnel. + tunnel_type (str): The type of GRE tunnel. Defaults to 'l3'. + kernel_interface (str): The associated kernel interface. Defaults to an empty string. + instance (int): The instance number derived from the interface name. + vpp (VPPControl): An instance of the VPPControl class for interacting with the VPP API. + """ + + # Mapping of tunnel types https://github.com/FDio/vpp/blob/stable/2406/src/plugins/gre/gre.api#L25-L35 + TUNNEL_TYPE_MAP = { + "l3": 0, + "teb": 1, + "erspan": 2, + } + + def __init__( + self, + ifname, + source_address, + remote, + tunnel_type: str = 'l3', + kernel_interface: str = '', + ): + """ + Initialize a GREInterface instance. + + Args: + ifname (str): The interface name. + source_address (str): The source IP address for the GRE tunnel. + remote (str): The remote IP address for the GRE tunnel. + tunnel_type (str): The type of GRE tunnel. Defaults to 'l3'. + kernel_interface (str): The associated kernel interface. Defaults to an empty string. + """ self.instance = int(ifname.removeprefix('gre')) self.ifname = ifname self.src_address = source_address self.dst_address = remote + self.tunnel_type = self.TUNNEL_TYPE_MAP[tunnel_type] self.kernel_interface = kernel_interface self.vpp = VPPControl() def add(self): """Create GRE interface - https://github.com/FDio/vpp/blob/stable/2306/src/plugins/gre/gre.api + https://github.com/FDio/vpp/blob/stable/2406/src/plugins/gre/gre.api Example: from vyos.vpp.interface import GREInterface - a = GREInterface(ifname='gre0', source_address='192.0.2.1', remote='203.0.113.25') + a = GREInterface(ifname='gre0', source_address='192.0.2.1', remote='203.0.113.25', tunnel_type='l3') a.add() """ self.vpp.api.gre_tunnel_add_del( @@ -52,6 +90,7 @@ def add(self): 'src': self.src_address, 'dst': self.dst_address, 'instance': self.instance, + 'type': self.tunnel_type, }, ) diff --git a/smoketest/scripts/cli/test_vpp.py b/smoketest/scripts/cli/test_vpp.py index 582c41c..ba0d0d7 100755 --- a/smoketest/scripts/cli/test_vpp.py +++ b/smoketest/scripts/cli/test_vpp.py @@ -552,7 +552,7 @@ def test_06_vpp_bonding(self): self.assertRegex( normalized_out, r'BondEthernet23\s+\d+\s+up', - "Interface BondEthernet23 is not in the expected state 'up'." + "Interface BondEthernet23 is not in the expected state 'up'.", ) # set kernel interface @@ -617,7 +617,7 @@ def test_06_vpp_bonding(self): self.assertRegex( normalized_out, r'BondEthernet23\s+\d+\s+up', - "Interface BondEthernet23 is not in the expected state 'up'." + "Interface BondEthernet23 is not in the expected state 'up'.", ) # delete vpp kernel-interface vlan diff --git a/src/conf_mode/vpp_interfaces_gre.py b/src/conf_mode/vpp_interfaces_gre.py index feff0d6..4cb1a71 100644 --- a/src/conf_mode/vpp_interfaces_gre.py +++ b/src/conf_mode/vpp_interfaces_gre.py @@ -124,7 +124,7 @@ def verify(config): return None # source-address and remote are mandatory options - required_keys = {'source_address', 'remote'} + required_keys = {'source_address', 'remote', 'tunnel_type'} if not all(key in config for key in required_keys): missing_keys = required_keys - set(config.keys()) raise ConfigError( @@ -159,7 +159,8 @@ def apply(config): src_addr = config.get('source_address') dst_addr = config.get('remote') kernel_interface = config.get('kernel_interface', '') - i = GREInterface(ifname, src_addr, dst_addr, kernel_interface) + tunnel_type = config.get('tunnel_type') + i = GREInterface(ifname, src_addr, dst_addr, tunnel_type, kernel_interface) i.add() # Add kernel-interface (LCP) if interface is not exist