From 888eec975ff765216e4c65ba15ed9176d7dee7ea Mon Sep 17 00:00:00 2001 From: Nataliia Solomko Date: Tue, 7 Oct 2025 18:21:06 +0300 Subject: T7750: VPP: CGNAT commit failure with vpptunX interface Allow using bond interfaces in CGNAT. Improve interface cleanup to rely on VPP API queries, as VPP config changes may modify interface indexes --- src/conf_mode/vpp.py | 5 ++++ src/conf_mode/vpp_kernel-interfaces.py | 6 +++++ src/conf_mode/vpp_nat_cgnat.py | 43 ++++++++++++++++++++-------------- 3 files changed, 36 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/conf_mode/vpp.py b/src/conf_mode/vpp.py index 81502c0b4..2d8c17e4f 100755 --- a/src/conf_mode/vpp.py +++ b/src/conf_mode/vpp.py @@ -373,6 +373,11 @@ def get_config(config=None): eth_ifaces_persist[iface]['bus_id'] = control_host.get_bus_name(iface) eth_ifaces_persist[iface]['dev_id'] = control_host.get_dev_id(iface) + # 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', 'nat44']): set_dependents('vpp_nat', conf) diff --git a/src/conf_mode/vpp_kernel-interfaces.py b/src/conf_mode/vpp_kernel-interfaces.py index 85706094e..d10449eec 100644 --- a/src/conf_mode/vpp_kernel-interfaces.py +++ b/src/conf_mode/vpp_kernel-interfaces.py @@ -19,6 +19,7 @@ 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 @@ -79,6 +80,9 @@ def get_config(config=None) -> dict: if vlans_removed: config['vlans_removed'] = vlans_removed + if conf.exists(['vpp', 'nat', 'cgnat']): + set_dependents('vpp_nat_cgnat', conf) + config['ifname'] = ifname return config @@ -185,6 +189,8 @@ def apply(config): 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 diff --git a/src/conf_mode/vpp_nat_cgnat.py b/src/conf_mode/vpp_nat_cgnat.py index be2386ba2..56d11b5a1 100644 --- a/src/conf_mode/vpp_nat_cgnat.py +++ b/src/conf_mode/vpp_nat_cgnat.py @@ -23,6 +23,15 @@ from vyos.configdiff import Diff from vyos.vpp.utils import cli_ifaces_list from vyos.vpp.nat.det44 import Det44 +from vyos.vpp.control_vpp import VPPControl + + +def _vpp_iface_name_transform(iface_name): + vpp_iface_name = iface_name + if vpp_iface_name.startswith('bond'): + # interface name in VPP is BondEthernetX + vpp_iface_name = vpp_iface_name.replace('bond', 'BondEthernet') + return vpp_iface_name def get_config(config=None) -> dict: @@ -120,16 +129,14 @@ def verify(config): f'Please choose a side for: {", ".join(conflict_ifaces)} ' ) - for interface in config['interface']['inside']: - if interface not in config['vpp_ifaces']: - raise ConfigError( - f'{interface} must be a VPP interface for inside CGNAT interface' - ) - for interface in config['interface']['outside']: - if interface not in config['vpp_ifaces']: - raise ConfigError( - f'{interface} must be a VPP interface for outside CGNAT interface' - ) + vpp = VPPControl() + for direction in ['inside', 'outside']: + for interface in config['interface'][direction]: + vpp_iface_name = _vpp_iface_name_transform(interface) + if vpp.get_sw_if_index(vpp_iface_name) is None: + raise ConfigError( + f'{interface} must be a VPP interface for {direction} CGNAT interface' + ) required_keys = {'outside_prefix', 'inside_prefix'} for rule in config['rule']: @@ -158,13 +165,11 @@ def apply(config): if 'effective' in config: remove_config = config.get('effective') # Delete inside interfaces - for interface in remove_config['interface']['inside']: - if interface not in config.get('interface', {}).get('inside', []): - cgnat.delete_det44_interface_inside(interface) + for interface in cgnat.get_det44_interfaces_inside(): + cgnat.delete_det44_interface_inside(interface) # Delete outside interfaces - for interface in remove_config['interface']['outside']: - if interface not in config.get('interface', {}).get('outside', []): - cgnat.delete_det44_interface_outside(interface) + for interface in cgnat.get_det44_interfaces_outside(): + cgnat.delete_det44_interface_outside(interface) # Delete CGNAT rules for rule in config['changed_rules']: if rule in remove_config.get('rule', {}): @@ -182,10 +187,12 @@ def apply(config): cgnat.enable_det44_plugin() # Add inside interfaces for interface in config['interface']['inside']: - cgnat.add_det44_interface_inside(interface) + vpp_iface_name = _vpp_iface_name_transform(interface) + cgnat.add_det44_interface_inside(vpp_iface_name) # Add outside interfaces for interface in config['interface']['outside']: - cgnat.add_det44_interface_outside(interface) + vpp_iface_name = _vpp_iface_name_transform(interface) + cgnat.add_det44_interface_outside(vpp_iface_name) # Add CGNAT rules for rule in config['changed_rules']: if rule in config.get('rule', {}): -- cgit v1.2.3