summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2023-08-23 20:14:37 +0200
committerChristian Breunig <christian@breunig.cc>2023-09-01 08:29:12 +0200
commit396329cc9a2419c5be8ddd0bc8fbde67fdcb03fa (patch)
tree3104f70666b7ff8b731690b4ddf50cda4ef9caba
parent0ba723bcdbf608ba73bedbba74a8aa9be1d7df7b (diff)
downloadvyos-1x-396329cc9a2419c5be8ddd0bc8fbde67fdcb03fa.tar.gz
vyos-1x-396329cc9a2419c5be8ddd0bc8fbde67fdcb03fa.zip
vrf: T5428: stop DHCP processes on VRF removal
This is a workaround for the priority inversion from T5492 ("CLI node priority is not inversed on node deletion"). As this is a corner case bug that's only triggered if an interface is removed from a VRF and also the VRF is removed in one commit, priorities are not honored. Thus we implement this workaround which stop the DHCP(v6) client processes on the VRF associated interfaces to get out the DHCP RELEASE message before interfaces are shut down. (cherry picked from commit 005151f77be5cf999689cfd03620bbc39df59018)
-rw-r--r--python/vyos/util.py21
-rwxr-xr-xsrc/conf_mode/vrf.py20
2 files changed, 39 insertions, 2 deletions
diff --git a/python/vyos/util.py b/python/vyos/util.py
index 03809fc83..ede22006c 100644
--- a/python/vyos/util.py
+++ b/python/vyos/util.py
@@ -912,3 +912,24 @@ def sysctl_write(name, value):
def is_ipv6_enabled() -> bool:
""" Check if IPv6 support on the system is enabled or not """
return (sysctl_read('net.ipv6.conf.all.disable_ipv6') == '0')
+
+def interface_exists(interface) -> bool:
+ import os
+ return os.path.exists(f'/sys/class/net/{interface}')
+
+def get_vrf_members(vrf: str) -> list:
+ """
+ Get list of interface VRF members
+ :param vrf: str
+ :return: list
+ """
+ import json
+ if not interface_exists(vrf):
+ raise ValueError(f'VRF "{vrf}" does not exist!')
+ output = cmd(f'ip --json --brief link show master {vrf}')
+ answer = json.loads(output)
+ interfaces = []
+ for data in answer:
+ if 'ifname' in data:
+ interfaces.append(data.get('ifname'))
+ return interfaces
diff --git a/src/conf_mode/vrf.py b/src/conf_mode/vrf.py
index def4cc70d..a3daf9ae9 100755
--- a/src/conf_mode/vrf.py
+++ b/src/conf_mode/vrf.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020-2022 VyOS maintainers and contributors
+# Copyright (C) 2020-2023 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -28,6 +28,8 @@ from vyos.util import cmd
from vyos.util import dict_search
from vyos.util import sysctl_write
from vyos.util import is_ipv6_enabled
+from vyos.util import interface_exists
+from vyos.util import get_vrf_members
from vyos import ConfigError
from vyos import airbag
airbag.enable()
@@ -155,7 +157,21 @@ def apply(vrf):
sysctl_write('net.ipv4.udp_l3mdev_accept', bind_all)
for tmp in (dict_search('vrf_remove', vrf) or []):
- if os.path.isdir(f'/sys/class/net/{tmp}'):
+ if interface_exists(tmp):
+ # T5492: deleting a VRF instance may leafe processes running
+ # (e.g. dhclient) as there is a depedency ordering issue in the CLI.
+ # We need to ensure that we stop the dhclient processes first so
+ # a proper DHCLP RELEASE message is sent
+ for interface in get_vrf_members(tmp):
+ vrf_iface = Interface(interface)
+ vrf_iface.set_dhcp(False)
+ vrf_iface.set_dhcpv6(False)
+
+ # Remove nftables conntrack zone map item
+ nft_del_element = f'delete element inet vrf_zones ct_iface_map {{ "{tmp}" }}'
+ cmd(f'nft {nft_del_element}')
+
+ # Delete the VRF Kernel interface
call(f'ip link delete dev {tmp}')
if 'name' in vrf: