summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2021-02-27 22:16:56 +0100
committerChristian Poessinger <christian@poessinger.com>2021-02-27 22:25:19 +0100
commite721c998ba977db9184d13e119dda4d56269d553 (patch)
treebcaf57e8d36e4e0860b09b3e3785c8e4db6a6f9f
parentebf93650bdd1a89304973274a4a795ef449e5440 (diff)
downloadvyos-1x-e721c998ba977db9184d13e119dda4d56269d553.tar.gz
vyos-1x-e721c998ba977db9184d13e119dda4d56269d553.zip
tunnel: T3366: support changing tunnel parameters for gre-bridge
Linux prevents changing parameters on a gretap (which is used by gre-bridge) interfaces. To overcome this limitation a tunnel must be destroyed and recreated on demand when gre-bridge is used.
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_tunnel.py31
-rwxr-xr-xsrc/conf_mode/interfaces-tunnel.py25
2 files changed, 52 insertions, 4 deletions
diff --git a/smoketest/scripts/cli/test_interfaces_tunnel.py b/smoketest/scripts/cli/test_interfaces_tunnel.py
index 5f3791655..a041427a8 100755
--- a/smoketest/scripts/cli/test_interfaces_tunnel.py
+++ b/smoketest/scripts/cli/test_interfaces_tunnel.py
@@ -19,6 +19,7 @@ import json
from vyos.configsession import ConfigSession
from vyos.configsession import ConfigSessionError
+from vyos.template import inc_ip
from vyos.util import cmd
from base_interfaces_test import BasicInterfaceTest
@@ -203,5 +204,35 @@ class TunnelInterfaceTest(BasicInterfaceTest.BaseTest):
# Check if commit is ok
self.session.commit()
+ def test_gretap_parameters_change(self):
+ interface = f'tun1040'
+ gre_key = '10'
+ encapsulation = 'gre-bridge'
+ tos = '20'
+
+ self.session.set(self._base_path + [interface, 'encapsulation', encapsulation])
+ self.session.set(self._base_path + [interface, 'local-ip', self.local_v4])
+ self.session.set(self._base_path + [interface, 'remote-ip', remote_ip4])
+
+ # Check if commit is ok
+ self.session.commit()
+
+ conf = tunnel_conf(interface)
+ self.assertEqual(mtu, conf['mtu'])
+ self.assertEqual(interface, conf['ifname'])
+ self.assertEqual('gretap', conf['linkinfo']['info_kind'])
+ self.assertEqual(self.local_v4, conf['linkinfo']['info_data']['local'])
+ self.assertEqual(remote_ip4, conf['linkinfo']['info_data']['remote'])
+ self.assertEqual(0, conf['linkinfo']['info_data']['ttl'])
+
+ # Change remote ip address (inc host by 2
+ new_remote = inc_ip(remote_ip4, 2)
+ self.session.set(self._base_path + [interface, 'remote-ip', new_remote])
+ # Check if commit is ok
+ self.session.commit()
+
+ conf = tunnel_conf(interface)
+ self.assertEqual(new_remote, conf['linkinfo']['info_data']['remote'])
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/src/conf_mode/interfaces-tunnel.py b/src/conf_mode/interfaces-tunnel.py
index cb6dca222..748a9d261 100755
--- a/src/conf_mode/interfaces-tunnel.py
+++ b/src/conf_mode/interfaces-tunnel.py
@@ -40,11 +40,22 @@ from vyos.ifconfig import SitIf
from vyos.ifconfig import Sit6RDIf
from vyos.template import is_ipv4
from vyos.template import is_ipv6
+from vyos.util import cmd
from vyos.util import dict_search
from vyos import ConfigError
from vyos import airbag
airbag.enable()
+def get_tunnel_encapsulation(interface):
+ """ Returns the used encapsulation protocol for given interface.
+ If interface does not exist, None is returned.
+ """
+ if not os.path.exists(f'/sys/class/net/{interface}'):
+ return None
+ from json import loads
+ tmp = loads(cmd(f'ip -d -j link show {interface}'))[0]
+ return tmp['linkinfo']['info_kind']
+
def get_config(config=None):
"""
Retrive CLI config as dictionary. Dictionary can never be empty, as at least
@@ -124,9 +135,15 @@ def generate(tunnel):
return None
def apply(tunnel):
- if 'deleted' in tunnel or 'encapsulation_changed' in tunnel:
- if tunnel['ifname'] in interfaces():
- tmp = Interface(tunnel['ifname'])
+ # If a gre-bridge tunnel is already existing we can not "simply" change
+ # local or remote addresses. This returns "Operation not supported" by the
+ # Kernel. There is no other solution to destroy and recreate the tunnel.
+ interface = tunnel['ifname']
+ encap = get_tunnel_encapsulation(interface)
+
+ if 'deleted' in tunnel or 'encapsulation_changed' in tunnel or encap == 'gretap':
+ if interface in interfaces():
+ tmp = Interface(interface)
tmp.remove()
if 'deleted' in tunnel:
return None
@@ -175,7 +192,7 @@ def apply(tunnel):
if dict_search(our_key, tunnel) and their_key in conf:
conf[their_key] = dict_search(our_key, tunnel)
- tun = klass(tunnel['ifname'], **conf)
+ tun = klass(interface, **conf)
tun.change_options()
tun.update(tunnel)