summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNataliia S. <81954790+natali-rs1985@users.noreply.github.com>2026-03-18 15:04:06 +0200
committerGitHub <noreply@github.com>2026-03-18 15:04:06 +0200
commit0b3114e33a8dfbbde48e1231322b201938add330 (patch)
tree7fc051d6b15813365d36627c96cd528d6376ee95 /src
parente58b538fa3d37a9843507d4cd670560a03e336f1 (diff)
parenta37c37da41b26cae0e71e05c260d14bbb1aa1610 (diff)
downloadvyos-1x-0b3114e33a8dfbbde48e1231322b201938add330.tar.gz
vyos-1x-0b3114e33a8dfbbde48e1231322b201938add330.zip
Merge pull request #5047 from natali-rs1985/T8230
vpp: T8230: Add support for PPPoE on bonding interfaces
Diffstat (limited to 'src')
-rwxr-xr-xsrc/conf_mode/service_pppoe-server.py47
-rwxr-xr-xsrc/conf_mode/vpp.py10
-rw-r--r--src/conf_mode/vpp_interfaces_bonding.py23
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