diff options
| author | Nataliia Solomko <natalirs1985@gmail.com> | 2026-03-12 12:05:01 +0200 |
|---|---|---|
| committer | Daniil Baturin <daniil@baturin.org> | 2026-03-17 20:19:17 +0000 |
| commit | a37c37da41b26cae0e71e05c260d14bbb1aa1610 (patch) | |
| tree | 28fc2620fd106b0fc9d5389bf2f9e3b75af71525 /src | |
| parent | e9f4d103284a456e10fb3776d26b9ff041f9352f (diff) | |
| download | vyos-1x-a37c37da41b26cae0e71e05c260d14bbb1aa1610.tar.gz vyos-1x-a37c37da41b26cae0e71e05c260d14bbb1aa1610.zip | |
vpp: T8230: Add support for PPPoE on bonding interfaces
Diffstat (limited to 'src')
| -rwxr-xr-x | src/conf_mode/service_pppoe-server.py | 47 | ||||
| -rwxr-xr-x | src/conf_mode/vpp.py | 10 | ||||
| -rw-r--r-- | src/conf_mode/vpp_interfaces_bonding.py | 23 |
3 files changed, 59 insertions, 21 deletions
diff --git a/src/conf_mode/service_pppoe-server.py b/src/conf_mode/service_pppoe-server.py index dbcbbabf2..3ec4464c2 100755 --- a/src/conf_mode/service_pppoe-server.py +++ b/src/conf_mode/service_pppoe-server.py @@ -69,6 +69,7 @@ def get_config(config=None): pppoe = get_accel_dict(conf, base, pppoe_chap_secrets) vpp_interface_base = ['vpp', 'settings', 'interface'] + vpp_bond_interface_base = ['interfaces', 'vpp', 'bonding'] if conf.exists(vpp_interface_base) and is_systemd_service_active('vpp.service'): vpp_ifaces = conf.get_config_dict( vpp_interface_base, @@ -76,23 +77,23 @@ def get_config(config=None): get_first_key=True, no_tag_node_value_mangle=True, ) + vpp_bond_ifaces = conf.get_config_dict( + vpp_bond_interface_base, + key_mangling=('-', '_'), + get_first_key=True, + no_tag_node_value_mangle=True, + ) + vpp_ifaces = vpp_ifaces | vpp_bond_ifaces pppoe['vpp_ifaces'] = vpp_ifaces for interface in pppoe.get('interface', {}): if base_ifname(interface) in vpp_ifaces: pppoe['interface'][interface]['vpp_cp'] = {} - pppoe['vpp_cp_interfaces'] = { - 'add': [ - ifname - for ifname, iface_conf in pppoe.get('interface', {}).items() - if 'vpp_cp' in iface_conf - ], - 'delete': [ - iface - for iface in node_changed(conf, base + ['interface']) - if base_ifname(iface) in pppoe.get('vpp_ifaces', {}) - ], - } + pppoe['vpp_cp_interfaces'] = [ + ifname + for ifname, iface_conf in pppoe.get('interface', {}).items() + if 'vpp_cp' in iface_conf + ] if not conf.exists(base): pppoe['remove'] = True @@ -112,6 +113,13 @@ def get_config(config=None): changed_vpp_ifaces = node_changed( conf, vpp_interface_base, expand_nodes=Diff.DELETE | Diff.ADD ) + changed_vpp_bond_ifaces = node_changed( + conf, + vpp_bond_interface_base, + recursive=True, + expand_nodes=Diff.DELETE | Diff.ADD, + ) + all_changed_vpp_ifaces = set(changed_vpp_ifaces) | set(changed_vpp_bond_ifaces) conditions = [ is_node_changed(conf, base + ['client-ip-pool']), is_node_changed(conf, base + ['client-ipv6-pool']), @@ -119,7 +127,7 @@ def get_config(config=None): is_node_changed(conf, base + ['authentication', 'radius', 'dynamic-author']), is_node_changed(conf, base + ['authentication', 'mode']), any( - base_ifname(iface) in changed_vpp_ifaces + base_ifname(iface) in all_changed_vpp_ifaces for iface in pppoe.get('interface', {}) ), ] @@ -208,14 +216,11 @@ def apply(pppoe): systemd_service = 'accel-ppp@pppoe.service' # delete pppoe mapping in vpp - vpp_cp_ifaces_delete = pppoe.get('vpp_cp_interfaces', {}).get('delete', []) - if 'vpp_ifaces' in pppoe and vpp_cp_ifaces_delete: + if 'vpp_ifaces' in pppoe: vpp = VPPControl() - # Make sure that the mapping really exists mapping = vpp.get_pppoe_interface_mapping() - for iface in vpp_cp_ifaces_delete: - if iface in mapping: - vpp.map_pppoe_interface(iface, is_add=False) + for dp_iface, cp_iface in mapping.items(): + vpp.delete_pppoe_mapping(dp_iface, cp_iface) if 'remove' in pppoe: call(f'systemctl stop {systemd_service}') @@ -230,11 +235,11 @@ def apply(pppoe): call(f'systemctl reload-or-restart {systemd_service}') # add pppoe mapping in vpp - vpp_cp_ifaces_add = pppoe.get('vpp_cp_interfaces', {}).get('add', []) + vpp_cp_ifaces_add = pppoe.get('vpp_cp_interfaces', []) if vpp_cp_ifaces_add: vpp = VPPControl() for iface in vpp_cp_ifaces_add: - vpp.map_pppoe_interface(iface, is_add=True) + vpp.map_pppoe_interface(iface) if __name__ == '__main__': diff --git a/src/conf_mode/vpp.py b/src/conf_mode/vpp.py index 22cf04020..a45d4dc65 100755 --- a/src/conf_mode/vpp.py +++ b/src/conf_mode/vpp.py @@ -303,6 +303,7 @@ def get_config(config=None): 'bond_members': bond_members, 'persist_config': eth_ifaces_persist, 'interfaces_vpp': interfaces_config, + 'pppoe_ifaces': pppoe_ifaces, 'remove': {}, } @@ -503,6 +504,15 @@ def verify(config): 'VPP cannot be removed while VPP interfaces exist. Remove all "interfaces vpp" first!' ) + # Find PPPoE ifaces where the base matches any VPP interface (base or VLAN) + pppoe_vpp_ifaces = [ + iface for iface in config.get('pppoe_ifaces', {}) if iface.startswith('vpp') + ] + if 'remove' in config and pppoe_vpp_ifaces: + raise ConfigError( + f'Cannot remove VPP: PPPoE server still uses VPP interface(s): {", ".join(pppoe_vpp_ifaces)}' + ) + # bail out early - looks like removal from running config if not config or 'remove' in config: return None diff --git a/src/conf_mode/vpp_interfaces_bonding.py b/src/conf_mode/vpp_interfaces_bonding.py index 582b82d99..8d9930a20 100644 --- a/src/conf_mode/vpp_interfaces_bonding.py +++ b/src/conf_mode/vpp_interfaces_bonding.py @@ -73,6 +73,9 @@ def get_config(config=None) -> dict: ifname, config = get_interface_dict(conf, base) + # Get pppoe-server interfaces + config['pppoe_ifaces'] = conf.list_nodes(['service', 'pppoe-server', 'interface']) + if not conf.exists(['vpp']) and not conf.exists(base): config['remove_vpp'] = True return config @@ -106,6 +109,10 @@ def get_config(config=None) -> dict: for bridge_iface in config['bridge_members'][ifname]: set_dependents('vpp_interfaces_bridge', conf, bridge_iface) + # PPPoE dependency + if any(i == ifname or i.startswith(f'{ifname}.') for i in config['pppoe_ifaces']): + set_dependents('pppoe_server', conf) + # NAT dependency if conf.exists(['vpp', 'nat', 'nat44']): set_dependents('vpp_nat_nat44', conf) @@ -124,6 +131,15 @@ def get_config(config=None) -> dict: def verify(config): + ifname = config['ifname'] + if 'deleted' in config and any( + i == ifname or i.startswith(f'{ifname}.') + for i in config.get('pppoe_ifaces', []) + ): + raise ConfigError( + 'Cannot remove interface: it is still in use by the PPPoE server' + ) + if 'remove_vpp' in config: return None @@ -167,6 +183,13 @@ def verify(config): f'Cannot use {mac}: it is a multicast MAC address. Please provide a unicast MAC address.' ) + for vif_remove in config.get('vif_remove', []): + vif_iface = f'{ifname}.{vif_remove}' + if vif_iface in config.get('pppoe_ifaces', []): + raise ConfigError( + f'Cannot remove interface {vif_iface}: it is still in use by the PPPoE server' + ) + def generate(config): pass |
