summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorViacheslav Hletenko <v.gletenko@vyos.io>2026-03-04 15:33:41 +0200
committerGitHub <noreply@github.com>2026-03-04 15:33:41 +0200
commit9fae68c92fe769da4f877c8df358868812a660ad (patch)
tree95d8b0c47cae0efcca44509a8f01ab6244f09900 /src
parent2a4d52b2b8c39f4f77b526ce80686247dd4d0f95 (diff)
parent32a5763872420ba8af53e3371c5c68e7369b5e62 (diff)
downloadvyos-1x-9fae68c92fe769da4f877c8df358868812a660ad.tar.gz
vyos-1x-9fae68c92fe769da4f877c8df358868812a660ad.zip
Merge pull request #5024 from natali-rs1985/T8328
vpp: T8328: Migrate xconnect interface to 'interfaces vpp xconnect'
Diffstat (limited to 'src')
-rw-r--r--src/conf_mode/vpp_interfaces_xconnect.py73
-rw-r--r--src/migration-scripts/vpp/5-to-621
2 files changed, 49 insertions, 45 deletions
diff --git a/src/conf_mode/vpp_interfaces_xconnect.py b/src/conf_mode/vpp_interfaces_xconnect.py
index 994332ba2..090d913b0 100644
--- a/src/conf_mode/vpp_interfaces_xconnect.py
+++ b/src/conf_mode/vpp_interfaces_xconnect.py
@@ -16,12 +16,13 @@
# 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 import ConfigError
+from vyos.configdict import get_interface_dict
+from vyos.utils.process import is_systemd_service_active
+
+from vyos.ifconfig.vpp import VPPXconnectInterface
from vyos.vpp.config_deps import deps_xconnect_dict
-from vyos.vpp.interface import XconnectInterface
from vyos.vpp.utils import cli_ifaces_list
@@ -38,26 +39,15 @@ def get_config(config=None) -> dict:
else:
conf = Config()
- base = ['vpp', 'interfaces', 'xconnect']
- vpp_interfaces = ['vpp', 'settings', 'interface']
+ base = ['interfaces', 'vpp', 'xconnect']
- 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,
- )
+ ifname, config = get_interface_dict(conf, base)
- if not conf.exists(['vpp']):
+ if not conf.exists(['vpp']) and not conf.exists(base):
config['remove_vpp'] = True
return config
- # Get effective config as we need full dicitonary per interface delete
+ # Get effective config as we need full dictionary per interface delete
effective_config = conf.get_config_dict(
base + [ifname],
key_mangling=('-', '_'),
@@ -66,46 +56,42 @@ def get_config(config=None) -> dict:
no_tag_node_value_mangle=True,
)
- if not config:
- config['remove'] = True
-
if effective_config:
config.update({'effective': effective_config})
- # Get global vpp interfaces for verify
- config['vpp_interfaces'] = conf.get_config_dict(
- vpp_interfaces,
- key_mangling=('-', '_'),
- get_first_key=True,
- no_tag_node_value_mangle=True,
- )
-
config['xconn_members'] = deps_xconnect_dict(conf)
config['vpp_ifaces'] = cli_ifaces_list(conf, 'candidate')
- config['ifname'] = ifname
-
return config
def verify(config):
- if 'remove' in config or 'remove_vpp' in config:
+ if 'deleted' in config or 'remove_vpp' in config:
return None
+ if not is_systemd_service_active('vpp.service'):
+ raise ConfigError(
+ 'Cannot configure layer 2 cross-connect: vpp.service is not running'
+ )
+
# Xconnect requires 2 members
if len(config.get('member', {}).get('interface')) != 2:
raise ConfigError('Cross connect requires 2 members')
- # Member must belong to VPP
+ not_allowed_prefixes = ('vppbond', 'vppbridge', 'vpplo')
for iface in config.get('member', {}).get('interface', []):
+ # Ensure the interface is allowed as xconnect member
+ if iface.startswith(not_allowed_prefixes):
+ raise ConfigError(f'{iface} cannot be configured as xconnect member')
+ # Member must belong to VPP
if iface not in config['vpp_ifaces']:
raise ConfigError(f'{iface} must be a VPP interface for xconnect')
- # Each interface can belong only to one xconnect
- for xconn_member, xconn_ifaces in config['xconn_members'].items():
- if len(xconn_ifaces) > 1:
+ # Each interface can belong only to one xconnect
+ xconn_members = config['xconn_members'][iface]
+ if len(xconn_members) > 1:
raise ConfigError(
- f'Interface {xconn_member} added to more than one xconnect: {xconn_ifaces}'
+ f'Interface {iface} added to more than one xconnect: {", ".join(xconn_members)}'
)
@@ -118,22 +104,19 @@ def apply(config):
return None
ifname = config.get('ifname')
+ xconnect = VPPXconnectInterface(ifname)
# Delete xconnect
if 'effective' in config:
remove_config = config.get('effective')
- members = remove_config.get('member', {}).get('interface')
- i = XconnectInterface(ifname, members=members)
- i.del_l2_xconnect()
+ members = remove_config['member']['interface']
+ xconnect.remove(members)
- if 'remove' in config:
+ if 'deleted' in config:
return None
# Add xconnect
- members = config.get('member', {}).get('interface')
- state = 'up' if 'disable' not in config else 'down'
- i = XconnectInterface(ifname, members=members, state=state)
- i.add_l2_xconnect()
+ xconnect.update(config)
return None
diff --git a/src/migration-scripts/vpp/5-to-6 b/src/migration-scripts/vpp/5-to-6
index 0131dee33..a816bb536 100644
--- a/src/migration-scripts/vpp/5-to-6
+++ b/src/migration-scripts/vpp/5-to-6
@@ -49,6 +49,8 @@
#
# Migrate bridge interface from vpp section to 'interfaces vpp bridge' (T8327)
#
+# Migrate xconnect interface from vpp section to 'interfaces vpp xconnect' (T8328)
+#
from vyos.configtree import ConfigTree
@@ -516,6 +518,24 @@ def _migrate_vpp_bridge_interface(config: ConfigTree) -> None:
config.delete(['vpp', 'interfaces'])
+def _migrate_vpp_xconnect_interface(config: ConfigTree) -> None:
+ base = ['vpp', 'interfaces', 'xconnect']
+ new_base = ['interfaces', 'vpp', 'xconnect']
+
+ if not config.exists(base):
+ return
+
+ config.set(new_base)
+
+ for ifname in config.list_nodes(base):
+ _migrate_interface(config, 'xconnect', ifname)
+
+ config.delete(base)
+
+ if len(config.list_nodes(['vpp', 'interfaces'])) == 0:
+ config.delete(['vpp', 'interfaces'])
+
+
def migrate(config: ConfigTree) -> None:
if not config.exists(['vpp']):
# Nothing to do
@@ -537,3 +557,4 @@ def migrate(config: ConfigTree) -> None:
_migrate_vpp_loopback_interface(config)
_migrate_vpp_gre_interface(config)
_migrate_vpp_bridge_interface(config)
+ _migrate_vpp_xconnect_interface(config)