diff options
| author | Christian Breunig <christian@breunig.cc> | 2026-03-04 20:30:20 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-04 20:30:20 +0100 |
| commit | 53488d0ef8ded005e75f853b6ca05342c3c8725d (patch) | |
| tree | caef839f6bb5f49ad6607a438755ca7585f6267c /src | |
| parent | ddaae274187916b3a7932372ee8944ddce8c5423 (diff) | |
| parent | d340acd74270728743807b1db4124b0fddcceec4 (diff) | |
| download | vyos-1x-53488d0ef8ded005e75f853b6ca05342c3c8725d.tar.gz vyos-1x-53488d0ef8ded005e75f853b6ca05342c3c8725d.zip | |
Merge pull request #5026 from natali-rs1985/T8339
vpp: T8339: Cleanup vpp interfaces and kernel-interfaces after migration
Diffstat (limited to 'src')
| -rwxr-xr-x | src/conf_mode/vpp.py | 18 | ||||
| -rw-r--r-- | src/conf_mode/vpp_interfaces_ethernet.py | 134 | ||||
| -rw-r--r-- | src/conf_mode/vpp_interfaces_geneve.py | 193 | ||||
| -rw-r--r-- | src/conf_mode/vpp_kernel-interfaces.py | 218 | ||||
| -rwxr-xr-x | src/op_mode/show_vpp_interfaces.py | 9 |
5 files changed, 6 insertions, 566 deletions
diff --git a/src/conf_mode/vpp.py b/src/conf_mode/vpp.py index 396cce548..2ae079c30 100755 --- a/src/conf_mode/vpp.py +++ b/src/conf_mode/vpp.py @@ -78,8 +78,6 @@ vpp_log = getLogger( dependency_interface_type_map = { 'vpp_interfaces_bonding': 'bonding', 'vpp_interfaces_bridge': 'bridge', - 'vpp_interfaces_ethernet': 'ethernet', - 'vpp_interfaces_geneve': 'geneve', 'vpp_interfaces_gre': 'gre', 'vpp_interfaces_ipip': 'ipip', 'vpp_interfaces_loopback': 'loopback', @@ -442,17 +440,6 @@ def get_config(config=None): # Dependencies for dependency, interface_type in dependency_interface_type_map.items(): - # if conf.exists(base + ['interfaces', interface_type]): - if effective_config.get('interfaces', {}).get(interface_type): - for iface, iface_config in ( - config.get('interfaces', {}).get(interface_type, {}).items() - ): - # filter unsupported config nodes - if interface_type == 'ethernet': - iface_filter_eth(conf, iface) - set_dependents(dependency, conf, iface) - - for dependency, interface_type in dependency_interface_type_map.items(): if conf.exists(['interfaces', 'vpp', interface_type]): for iface, iface_config in interfaces_config.get( interface_type, {} @@ -466,11 +453,6 @@ def get_config(config=None): no_tag_node_value_mangle=True, ) - # kernel-interfaces dependency - if effective_config.get('kernel_interfaces'): - for iface in config.get('kernel_interfaces', {}): - set_dependents('vpp_kernel_interface', conf, iface) - # NAT dependency if conf.exists(['vpp', 'nat', 'nat44']): set_dependents('vpp_nat_nat44', conf) diff --git a/src/conf_mode/vpp_interfaces_ethernet.py b/src/conf_mode/vpp_interfaces_ethernet.py deleted file mode 100644 index 81050444e..000000000 --- a/src/conf_mode/vpp_interfaces_ethernet.py +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) VyOS Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -import os - -from vyos.config import Config -from vyos.configdep import set_dependents -from vyos import ConfigError -from vyos.vpp.config_verify import verify_vpp_remove_xconnect_interface - - -def get_config(config=None) -> dict: - """Get Ethernet interface configuration - - Args: - config (vyos.config.Config, optional): The VyOS configuration dictionary - Returns: - dict: Ethernet interface configuration - """ - if config: - conf = config - else: - conf = Config() - - base = ['vpp', 'interfaces', 'ethernet'] - base_interfaces_xconnect = ['vpp', 'interfaces', 'xconnect'] - - ifname = os.environ['VYOS_TAGNODE_VALUE'] - - # Get effective config as we need full dicitonary per interface delete - effective_config = conf.get_config_dict( - base + [ifname], - key_mangling=('-', '_'), - effective=True, - get_first_key=True, - no_tag_node_value_mangle=True, - ) - - if not conf.exists(base + [ifname]): - config = conf.get_config_dict( - base + [ifname], - key_mangling=('-', '_'), - get_first_key=True, - no_tag_node_value_mangle=True, - ) - config.update({'remove': effective_config}) - else: - # Get config_dict with default values - config = conf.get_config_dict( - base + [ifname], - key_mangling=('-', '_'), - get_first_key=True, - no_tag_node_value_mangle=True, - with_defaults=True, - with_recursive_defaults=True, - ) - - # Get global 'vpp interfaces xconnect' - config['vpp_interfaces_xconnect'] = conf.get_config_dict( - base_interfaces_xconnect, - key_mangling=('-', '_'), - get_first_key=True, - no_tag_node_value_mangle=True, - ) - - # Dependency - for xcon_name, xcon_config in config.get('vpp_interfaces_xconnect').items(): - for member_name in xcon_config.get('member', {}).get('interface', []): - if member_name == ifname: - set_dependents('vpp_interfaces_xconnect', conf, xcon_name) - - if conf.exists(base + [ifname, 'kernel-interface']): - iface = config.get('kernel_interface') - if conf.exists(['vpp', 'kernel-interfaces', iface]): - set_dependents('vpp_kernel_interface', conf, iface) - - config['ifname'] = ifname - return config - - -def verify(config): - verify_vpp_remove_xconnect_interface(config) - if 'remove' in config: - return None - - -def generate(config): - pass - - -def apply(config): - # Delete interface - if 'remove' in config: - pass - # remove_config = config.get('remove') - # ifname = config.get('ifname') - # src_addr = remove_config.get('source_address') - # dst_addr = remove_config.get('remote') - # vni = int(remove_config.get('vni')) - # v = VXLANInterface(ifname, src_addr, dst_addr, vni) - # v.delete() - else: - pass - # ifname = config.get('ifname') - # kernel_interface = config.get('kernel_interface', '') - # v = VXLANInterface(ifname, src_addr, dst_addr, vni, kernel_interface) - # v.add() - return None - - -if __name__ == '__main__': - try: - c = get_config() - verify(c) - generate(c) - apply(c) - except ConfigError as e: - print(e) - exit(1) diff --git a/src/conf_mode/vpp_interfaces_geneve.py b/src/conf_mode/vpp_interfaces_geneve.py deleted file mode 100644 index efac4e65a..000000000 --- a/src/conf_mode/vpp_interfaces_geneve.py +++ /dev/null @@ -1,193 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) VyOS Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -import os - -from vyos import ConfigError - -from vyos.config import Config -from vyos.configdict import leaf_node_changed -from vyos.configdep import set_dependents, call_dependents -from vyos.template import is_interface - -from vyos.vpp.interface import GeneveInterface -from vyos.vpp.config_deps import deps_xconnect_dict -from vyos.vpp.config_verify import ( - verify_vpp_remove_kernel_interface, - verify_vpp_change_kernel_interface, - verify_vpp_remove_xconnect_interface, - verify_vpp_exists_kernel_interface, -) -from vyos.vpp.utils import cli_ifaces_lcp_kernel_list - - -def get_config(config=None) -> dict: - """Get Geneve interface configuration - - Args: - config (vyos.config.Config, optional): The VyOS configuration dictionary - recursive_defaults (bool, optional): Include recursive defaults - Returns: - dict: Geneve interface configuration - """ - if config: - conf = config - else: - conf = Config() - - base = ['vpp', 'interfaces', 'geneve'] - base_kernel_interfaces = ['vpp', 'kernel-interfaces'] - - ifname = os.environ['VYOS_TAGNODE_VALUE'] - - # Get config_dict with default values - config = conf.get_config_dict( - base + [ifname], - key_mangling=('-', '_'), - get_first_key=True, - no_tag_node_value_mangle=True, - with_defaults=True, - with_recursive_defaults=True, - ) - - if not conf.exists(['vpp']): - config['remove_vpp'] = True - return config - - # Get effective config as we need full dicitonary per interface delete - effective_config = conf.get_config_dict( - base + [ifname], - key_mangling=('-', '_'), - effective=True, - get_first_key=True, - no_tag_node_value_mangle=True, - ) - - if effective_config: - config.update({'effective': effective_config}) - - if not conf.exists(base + [ifname]): - config['remove'] = True - - # Get global 'vpp kernel-interfaces' for verify - config['vpp_kernel_interfaces'] = conf.get_config_dict( - base_kernel_interfaces, - key_mangling=('-', '_'), - get_first_key=True, - no_tag_node_value_mangle=True, - ) - - tmp = leaf_node_changed(conf, base + [ifname, 'kernel-interface']) - if tmp: - config['kernel_interface_removed'] = tmp - - # list of all kernel interfaces `vpp interface xxx kernel-interface xxx` - config['candidate_kernel_interfaces'] = cli_ifaces_lcp_kernel_list(conf) - - # Dependency - config['xconn_members'] = deps_xconnect_dict(conf) - if ifname in config['xconn_members']: - for xconn_iface in config['xconn_members'][ifname]: - set_dependents('vpp_interfaces_xconnect', conf, xconn_iface) - - if effective_config.get('kernel_interface'): - if conf.exists(base + [ifname, 'kernel-interface']): - iface = config.get('kernel_interface') - if conf.exists(['vpp', 'kernel-interfaces', iface]): - set_dependents('vpp_kernel_interface', conf, iface) - - config['ifname'] = ifname - return config - - -def verify(config): - # No need to verify anything if vpp is removed - if 'remove_vpp' in config: - return None - - # Verify that removed kernel interface is not used in 'vpp kernel-interfaces'. - # vpp interfaces geneve geneveX kernel-interface vpp-tunX - # vpp kernel-interface vpp-tunX - verify_vpp_remove_kernel_interface(config) - - verify_vpp_remove_xconnect_interface(config) - - if 'remove' in config: - return None - - required_keys = {'source_address', 'remote', 'vni'} - if not all(key in config for key in required_keys): - missing_keys = required_keys - set(config.keys()) - raise ConfigError( - f"Required options are missing: {', '.join(missing_keys).replace('_', '-')}" - ) - - # Change 'vpp interfaces geneve geneveX kernel-interface vpp-tunX' - # => 'vpp interfaces geneve geneveX kernel-interface vpp-tunY' - # check if we have kernel interface config 'vpp kernel-interface vpp-tunX' - verify_vpp_change_kernel_interface(config) - verify_vpp_exists_kernel_interface(config) - - -def generate(config): - pass - - -def apply(config): - if 'remove_vpp' in config: - return None - - ifname = config.get('ifname') - # Delete interface - if 'effective' in config: - remove_config = config.get('effective') - src_addr = remove_config.get('source_address') - dst_addr = remove_config.get('remote') - vni = int(remove_config.get('vni')) - i = GeneveInterface(ifname, src_addr, dst_addr, vni) - i.delete() - - if 'remove' in config: - return None - - # Add interface - src_addr = config.get('source_address') - dst_addr = config.get('remote') - vni = int(config.get('vni')) - kernel_interface = config.get('kernel_interface', '') - i = GeneveInterface(ifname, src_addr, dst_addr, vni, kernel_interface) - i.add() - - # Add kernel-interface (LCP) if interface is not exist - if 'kernel_interface' in config and not is_interface(kernel_interface): - i.kernel_add() - - call_dependents() - - return None - - -if __name__ == '__main__': - try: - c = get_config() - verify(c) - generate(c) - apply(c) - except ConfigError as e: - print(e) - exit(1) diff --git a/src/conf_mode/vpp_kernel-interfaces.py b/src/conf_mode/vpp_kernel-interfaces.py deleted file mode 100644 index d18a5d3e5..000000000 --- a/src/conf_mode/vpp_kernel-interfaces.py +++ /dev/null @@ -1,218 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) VyOS Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -import os - -from vyos.config import Config -from vyos.configdep import set_dependents, call_dependents -from vyos.configdict import leaf_node_changed -from vyos.configdict import node_changed -from vyos import ConfigError -from vyos.ifconfig import Interface -from vyos.utils.network import interface_exists -from vyos.utils.process import call -from vyos.vpp import VPPControl - - -def get_config(config=None) -> dict: - if config: - conf = config - else: - conf = Config() - - base = ['vpp', 'kernel-interfaces'] - base_settings = ['vpp', 'settings'] - - ifname = os.environ['VYOS_TAGNODE_VALUE'] - - # Get config_dict with default values - config = conf.get_config_dict( - base + [ifname], - key_mangling=('-', '_'), - get_first_key=True, - no_tag_node_value_mangle=True, - with_defaults=True, - ) - - if not conf.exists(['vpp']): - config['remove_vpp'] = True - return config - - # Get 'vpp settings' config with default values - config_settings = conf.get_config_dict( - base_settings, - key_mangling=('-', '_'), - get_first_key=True, - no_tag_node_value_mangle=True, - with_defaults=True, - ) - config['vpp_settings'] = config_settings - - # Get effective config as we need full dicitonary per interface delete - if __name__ == '__main__': - effective_config = conf.get_config_dict( - base + [ifname], - key_mangling=('-', '_'), - effective=True, - get_first_key=True, - no_tag_node_value_mangle=True, - ) - # if a file was started as dependency, we are starting from empty config - else: - effective_config = {} - - if effective_config: - config.update({'effective': effective_config}) - - address_removed = leaf_node_changed(conf, base + [ifname, 'address']) - if address_removed: - config['address_removed'] = address_removed - - description_removed = leaf_node_changed(conf, base + [ifname, 'description']) - if description_removed: - config['description_removed'] = {} - - vlans_removed = node_changed(conf, base + [ifname, 'vif']) - if vlans_removed: - config['vlans_removed'] = vlans_removed - - if conf.exists(['vpp', 'nat', 'cgnat']): - set_dependents('vpp_nat_cgnat', conf) - if conf.exists(['vpp', 'nat', 'nat44']): - set_dependents('vpp_nat_nat44', conf) - - config['ifname'] = ifname - - return config - - -def verify(config): - if 'remove' in config or 'remove_vpp' in config: - return None - - # Interface must exists before it is configured - if not interface_exists(config['ifname']): - raise ConfigError( - f'Interface {config["ifname"]} must be created before using in configuration' - ) - - -def generate(config): - pass - - -def apply(config): - if 'remove_vpp' in config: - return None - - ifname = config.get('ifname') - i = Interface(ifname) - # update/remove addresses - if 'address_removed' in config: - for address in config['address_removed']: - i.del_addr(address) - # remove description - if 'description_removed' in config: - i.set_alias('') - - # remove VLANs - if 'vlans_removed' in config: - for vlan in config['vlans_removed']: - call(f'ip link del dev {ifname}.{vlan}') - - # Delete - if 'remove' in config: - pass - else: - # Add address - if 'address' in config: - for address in config['address']: - i.add_addr(address) - # Set MTU - if 'mtu' in config: - i.set_mtu(config.get('mtu')) - # Set description - if 'description' in config: - i.set_alias(config.get('description')) - # Admin state down - if 'disable' in config: - i.set_admin_state('down') - else: - i.set_admin_state('up') - - for vlan, vlan_config in config.get('vif', {}).items(): - if vlan not in config.get('effective', {}).get('vif', {}).keys(): - call( - f'ip link add link {ifname} name {ifname}.{vlan} type vlan id {vlan}' - ) - call(f'ip link set dev {ifname}.{vlan} up') - v = Interface(f'{ifname}.{vlan}') - - # VLAN address - addresses_effective = ( - config.get('effective', {}) - .get('vif', {}) - .get(vlan, {}) - .get('address', []) - ) - addresses_candidate = vlan_config.get('address', []) - - for ipaddr in addresses_effective: - if ipaddr not in addresses_candidate: - v.del_addr(ipaddr) - for ipaddr in addresses_candidate: - if ipaddr not in addresses_effective: - v.add_addr(ipaddr) - - # VLAN description - description_effective = ( - config.get('effective', {}) - .get('vif', {}) - .get(vlan, {}) - .get('description', '') - ) - description_candidate = vlan_config.get('description', '') - - if description_candidate: - v.set_alias(description_candidate) - elif description_effective and not description_candidate: - v.set_alias('') - - v.set_admin_state('up') - - # Set rx-mode - rx_mode = config['vpp_settings'].get('interface_rx_mode') - if rx_mode: - vpp_control = VPPControl() - lcp_name = vpp_control.lcp_pair_find(kernel_name=ifname).get('vpp_name_kernel') - vpp_control.iface_rxmode(lcp_name, rx_mode) - - call_dependents() - - return None - - -if __name__ == '__main__': - try: - c = get_config() - verify(c) - generate(c) - apply(c) - except ConfigError as e: - print(e) - exit(1) diff --git a/src/op_mode/show_vpp_interfaces.py b/src/op_mode/show_vpp_interfaces.py index c159ad0aa..d5dd08247 100755 --- a/src/op_mode/show_vpp_interfaces.py +++ b/src/op_mode/show_vpp_interfaces.py @@ -248,9 +248,12 @@ if __name__ == '__main__': vpp_interfaces = [] vpp_ethernet = config.list_nodes('vpp settings interface') vpp_interfaces.extend(vpp_ethernet) - if config.exists('vpp kernel-interfaces'): - vpp_kernel_interfaces = config.list_nodes('vpp kernel-interfaces') - vpp_interfaces.extend(vpp_kernel_interfaces) + if config.exists('interfaces vpp'): + for iface_type in config.list_nodes('interfaces vpp'): + vpp_kernel_interfaces = config.list_nodes( + f'interfaces vpp {iface_type}' + ) + vpp_interfaces.extend(vpp_kernel_interfaces) print(show_interfaces(interfaces_list=vpp_interfaces)) if args.hardware: |
