diff options
Diffstat (limited to 'python/vyos')
-rw-r--r-- | python/vyos/ifconfig/interface.py | 30 | ||||
-rw-r--r-- | python/vyos/utils/network.py | 13 |
2 files changed, 34 insertions, 9 deletions
diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index fa79395ff..fd4f5b269 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -36,6 +36,7 @@ from vyos.template import render from vyos.utils.network import mac2eui64 from vyos.utils.dict import dict_search from vyos.utils.network import get_interface_config +from vyos.utils.network import get_vrf_tableid from vyos.utils.process import is_systemd_service_active from vyos.template import is_ipv4 from vyos.template import is_ipv6 @@ -387,25 +388,33 @@ class Interface(Control): cmd = 'ip link del dev {ifname}'.format(**self.config) return self._cmd(cmd) - def _set_vrf_ct_zone(self, vrf): + def _set_vrf_ct_zone(self, vrf, old_vrf_tableid=None): """ Add/Remove rules in nftables to associate traffic in VRF to an individual conntack zone """ + + def nft_check_and_run(nft_command): + # Check if deleting is possible first to avoid raising errors + _, err = self._popen(f'nft --check {nft_command}') + if not err: + # Remove map element + self._cmd(f'nft {nft_command}') + if vrf: # Get routing table ID for VRF - vrf_table_id = get_interface_config(vrf).get('linkinfo', {}).get( - 'info_data', {}).get('table') + vrf_table_id = get_vrf_tableid(vrf) # Add map element with interface and zone ID if vrf_table_id: + # delete old table ID from nftables if it has changed, e.g. interface moved to a different VRF + if old_vrf_tableid and old_vrf_tableid != int(vrf_table_id): + nft_del_element = f'delete element inet vrf_zones ct_iface_map {{ "{self.ifname}" }}' + nft_check_and_run(nft_del_element) + self._cmd(f'nft add element inet vrf_zones ct_iface_map {{ "{self.ifname}" : {vrf_table_id} }}') else: nft_del_element = f'delete element inet vrf_zones ct_iface_map {{ "{self.ifname}" }}' - # Check if deleting is possible first to avoid raising errors - _, err = self._popen(f'nft --check {nft_del_element}') - if not err: - # Remove map element - self._cmd(f'nft {nft_del_element}') + nft_check_and_run(nft_del_element) def get_min_mtu(self): """ @@ -559,8 +568,11 @@ class Interface(Control): if tmp == vrf: return None + # Get current VRF table ID + old_vrf_tableid = get_vrf_tableid(self.ifname) self.set_interface('vrf', vrf) - self._set_vrf_ct_zone(vrf) + self._set_vrf_ct_zone(vrf, old_vrf_tableid) + return True def set_arp_cache_tmo(self, tmo): """ diff --git a/python/vyos/utils/network.py b/python/vyos/utils/network.py index a3bd5c58f..8befe370f 100644 --- a/python/vyos/utils/network.py +++ b/python/vyos/utils/network.py @@ -70,6 +70,19 @@ def get_interface_vrf(interface): return tmp['master'] return 'default' +def get_vrf_tableid(interface: str): + """ Return VRF table ID for given interface name or None """ + from vyos.utils.dict import dict_search + table = None + tmp = get_interface_config(interface) + # Check if we are "the" VRF interface + if dict_search('linkinfo.info_kind', tmp) == 'vrf': + table = tmp['linkinfo']['info_data']['table'] + # or an interface bound to a VRF + elif dict_search('linkinfo.info_slave_kind', tmp) == 'vrf': + table = tmp['linkinfo']['info_slave_data']['table'] + return table + def get_interface_config(interface): """ Returns the used encapsulation protocol for given interface. If interface does not exist, None is returned. |