summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNataliia Solomko <natalirs1985@gmail.com>2026-01-15 14:29:42 +0200
committerNataliia Solomko <natalirs1985@gmail.com>2026-01-19 12:10:51 +0200
commit8f0f9dad4eff0ab09ba168c16462f136eaa78410 (patch)
tree418ffac02eeb37fc82774c0e572de0f295f4bfdf /src
parent7fea6b6dbbd786bf6a32c496fc70ca9e9b5f8b1f (diff)
downloadvyos-1x-8f0f9dad4eff0ab09ba168c16462f136eaa78410.tar.gz
vyos-1x-8f0f9dad4eff0ab09ba168c16462f136eaa78410.zip
pppoe-server: T8143: Set 'vpp-cp' option automatically if interface is in VPP
Diffstat (limited to 'src')
-rwxr-xr-xsrc/conf_mode/service_pppoe-server.py80
-rwxr-xr-xsrc/conf_mode/vpp.py38
-rw-r--r--src/migration-scripts/pppoe-server/11-to-1231
3 files changed, 89 insertions, 60 deletions
diff --git a/src/conf_mode/service_pppoe-server.py b/src/conf_mode/service_pppoe-server.py
index bfa475b95..3d1fcab98 100755
--- a/src/conf_mode/service_pppoe-server.py
+++ b/src/conf_mode/service_pppoe-server.py
@@ -20,11 +20,12 @@ from sys import exit
from vyos.config import Config
from vyos.configdict import get_accel_dict
-from vyos.configdict import is_node_changed
-from vyos.configdiff import get_config_diff, Diff
+from vyos.configdict import is_node_changed, node_changed
+from vyos.configdiff import Diff
from vyos.configverify import verify_interface_exists
from vyos.template import render
from vyos.utils.process import call
+from vyos.utils.process import is_systemd_service_active
from vyos.utils.dict import dict_search
from vyos.accel_ppp_util import verify_accel_ppp_name_servers
from vyos.accel_ppp_util import verify_accel_ppp_wins_servers
@@ -40,6 +41,12 @@ airbag.enable()
pppoe_conf = r'/run/accel-pppd/pppoe.conf'
pppoe_chap_secrets = r'/run/accel-pppd/pppoe.chap-secrets'
+
+def base_ifname(ifname):
+ # Get the base interface name without VLAN
+ return ifname.split('.')[0]
+
+
def convert_pado_delay(pado_delay):
new_pado_delay = {'delays_without_sessions': [],
'delays_with_sessions': []}
@@ -60,18 +67,18 @@ def get_config(config=None):
# retrieve common dictionary keys
pppoe = get_accel_dict(conf, base, pppoe_chap_secrets)
- if conf.exists(['vpp']):
- pppoe['vpp_config'] = conf.get_config_dict(
- ['vpp'],
+ vpp_interface_base = ['vpp', 'settings', 'interface']
+ if conf.exists(vpp_interface_base) and is_systemd_service_active('vpp.service'):
+ vpp_ifaces = conf.get_config_dict(
+ vpp_interface_base,
key_mangling=('-', '_'),
get_first_key=True,
no_tag_node_value_mangle=True,
)
-
- diff = get_config_diff(conf)
- node_diff = diff.get_child_nodes_diff(
- base + ['interface'], expand_nodes=Diff.DELETE, recursive=True
- )
+ 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': [
@@ -81,8 +88,8 @@ def get_config(config=None):
],
'delete': [
iface
- for iface, iface_config in node_diff.get('delete').items()
- if 'vpp-cp' in iface_config
+ for iface in node_changed(conf, base + ['interface'])
+ if base_ifname(iface) in pppoe.get('vpp_ifaces', {})
],
}
@@ -98,14 +105,23 @@ def get_config(config=None):
pado_delay = dict_search('pado_delay', pppoe)
pppoe['pado_delay'] = convert_pado_delay(pado_delay)
- # reload-or-restart does not implemented in accel-ppp
+ # reload-or-restart is not implemented in accel-ppp
# use this workaround until it will be implemented
# https://phabricator.accel-ppp.org/T3
- conditions = [is_node_changed(conf, base + ['client-ip-pool']),
- is_node_changed(conf, base + ['client-ipv6-pool']),
- is_node_changed(conf, base + ['interface']),
- is_node_changed(conf, base + ['authentication','radius','dynamic-author']),
- is_node_changed(conf, base + ['authentication','mode'])]
+ changed_vpp_ifaces = node_changed(
+ conf, vpp_interface_base, expand_nodes=Diff.DELETE | Diff.ADD
+ )
+ conditions = [
+ is_node_changed(conf, base + ['client-ip-pool']),
+ is_node_changed(conf, base + ['client-ipv6-pool']),
+ is_node_changed(conf, base + ['interface']),
+ is_node_changed(conf, base + ['authentication', 'radius', 'dynamic-author']),
+ is_node_changed(conf, base + ['authentication', 'mode']),
+ any(
+ base_ifname(iface) in changed_vpp_ifaces
+ for iface in pppoe.get('interface', {})
+ ),
+ ]
if any(conditions):
pppoe.update({'restart_required': {}})
pppoe['server_type'] = 'pppoe'
@@ -154,27 +170,19 @@ def verify(pppoe):
# Check is interface exists in the system
for interface, interface_config in pppoe['interface'].items():
- verify_interface_exists(pppoe, interface, warning_only=True)
+ # Interfaces integrated with the control-plane in VPP must exist in the system
+ warning_only = 'vpp_cp' not in interface_config
+ verify_interface_exists(pppoe, interface, warning_only=warning_only)
- if 'vlan_mon' in interface_config and not 'vlan' in interface_config:
- raise ConfigError('Option "vlan-mon" requires "vlan" to be set!')
-
- vpp_cp_interfaces = pppoe.get('vpp_cp_interfaces', {}).get('add', [])
- if vpp_cp_interfaces:
- try:
- vpp = VPPControl()
- except Exception:
+ if 'vlan_mon' in interface_config and base_ifname(interface) in pppoe.get(
+ 'vpp_ifaces', {}
+ ):
raise ConfigError(
- 'PPPoE control-plane integration with VPP is enabled on '
- f'interface(s) {", ".join(vpp_cp_interfaces)} '
- 'but VPP service was not started'
+ f'Cannot set option "vlan-mon": interface {interface} is integrated with control-plane!'
)
- for iface in vpp_cp_interfaces:
- if vpp.get_sw_if_index(iface) is None:
- raise ConfigError(
- f'{iface} should be a VPP interface for control-plane integration'
- )
+ if 'vlan_mon' in interface_config and not 'vlan' in interface_config:
+ raise ConfigError('Option "vlan-mon" requires "vlan" to be set!')
return None
@@ -196,7 +204,7 @@ def apply(pppoe):
# delete pppoe mapping in vpp
vpp_cp_ifaces_delete = pppoe.get('vpp_cp_interfaces', {}).get('delete', [])
- if 'vpp_config' in pppoe and vpp_cp_ifaces_delete:
+ if 'vpp_ifaces' in pppoe and vpp_cp_ifaces_delete:
vpp = VPPControl()
for iface in vpp_cp_ifaces_delete:
vpp.map_pppoe_interface(iface, is_add=False)
diff --git a/src/conf_mode/vpp.py b/src/conf_mode/vpp.py
index 4cbfab6bc..274cd1da5 100755
--- a/src/conf_mode/vpp.py
+++ b/src/conf_mode/vpp.py
@@ -265,25 +265,24 @@ def get_config(config=None):
# to be reinitialized after the commit
set_dependents('ethernet', conf, removed_iface)
- # Get interfaces that are used in PPPoe for control-plane integration
- pppoe_conf = conf.get_config_dict(
- ['service', 'pppoe-server'],
+ # Get interfaces that should be used in PPPoE for control-plane integration
+ pppoe_ifaces = conf.get_config_dict(
+ ['service', 'pppoe-server', 'interface'],
key_mangling=('-', '_'),
get_first_key=True,
no_tag_node_value_mangle=True,
)
- pppoe_map_ifaces = [
- ifname
- for ifname, iface_conf in pppoe_conf.get('interface', {}).items()
- if 'vpp_cp' in iface_conf
+ changed_pppoe_ifaces = [
+ iface for iface in pppoe_ifaces if iface.split('.')[0] in tmp
]
if not conf.exists(base):
+ if changed_pppoe_ifaces:
+ set_dependents('pppoe_server', conf)
return {
'removed_ifaces': removed_ifaces,
'xconn_members': xconn_members,
'persist_config': eth_ifaces_persist,
- **({'pppoe_ifaces': pppoe_map_ifaces} if pppoe_map_ifaces else {}),
}
config = conf.get_config_dict(
@@ -455,28 +454,19 @@ def get_config(config=None):
set_dependents('vpp_ipfix', conf)
# PPPoE dependency
- if pppoe_map_ifaces:
- config['pppoe_ifaces'] = pppoe_map_ifaces
+ added_pppoe_ifaces = [
+ iface
+ for iface in pppoe_ifaces
+ if iface.split('.')[0] in config.get('settings', {}).get('interface', {})
+ ]
+ changed_pppoe_ifaces.extend(added_pppoe_ifaces)
+ if changed_pppoe_ifaces:
set_dependents('pppoe_server', conf)
return config
def verify(config):
- # Cannot remove interface if PPPoE control-plane is still enabled
- removed_ifaces = [iface['iface_name'] for iface in config.get('removed_ifaces', [])]
- pppoe_removed_ifaces = [
- p
- for p in config.get('pppoe_ifaces', [])
- for r in removed_ifaces
- if p == r or p.startswith(f'{r}.')
- ]
- if pppoe_removed_ifaces:
- raise ConfigError(
- f'{", ".join(pppoe_removed_ifaces)} still in use by the PPPoE server. '
- 'Disable PPPoE control-plane integration with VPP before proceeding.'
- )
-
# Check remove VPP interface that used in IPFIX
_check_removed_interfaces(
config, 'IPFIX monitoring', config.get('ipfix', {}).get('interface', {})
diff --git a/src/migration-scripts/pppoe-server/11-to-12 b/src/migration-scripts/pppoe-server/11-to-12
new file mode 100644
index 000000000..d38ba0367
--- /dev/null
+++ b/src/migration-scripts/pppoe-server/11-to-12
@@ -0,0 +1,31 @@
+# Copyright VyOS maintainers and contributors <maintainers@vyos.io>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+# Delete 'vpp-cp' option from interface settings
+# because it will be set automatically (T8143)
+
+from vyos.configtree import ConfigTree
+
+base = ['service', 'pppoe-server']
+
+def migrate(config: ConfigTree) -> None:
+ if not config.exists(base):
+ return
+
+ for interface in config.list_nodes(base + ['interface']):
+ base_path = base + ['interface', interface]
+ # Delete vpp-cp option from PPPoE interface settings
+ if config.exists(base_path + ['vpp-cp']):
+ config.delete(base_path + ['vpp-cp'])