summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/conf_mode/vpp.py30
-rw-r--r--src/conf_mode/vpp_interfaces_bonding.py8
-rw-r--r--src/conf_mode/vpp_interfaces_bridge.py129
-rw-r--r--src/conf_mode/vpp_interfaces_gre.py14
-rw-r--r--src/conf_mode/vpp_interfaces_vxlan.py8
-rw-r--r--src/migration-scripts/vpp/5-to-621
-rwxr-xr-xsrc/op_mode/vpp.py12
7 files changed, 98 insertions, 124 deletions
diff --git a/src/conf_mode/vpp.py b/src/conf_mode/vpp.py
index 92777a16a..396cce548 100755
--- a/src/conf_mode/vpp.py
+++ b/src/conf_mode/vpp.py
@@ -45,6 +45,7 @@ from vyos.utils.process import is_systemd_service_active
from vyos.vpp import VPPControl
from vyos.vpp import control_host
from vyos.vpp import VppNotRunningError
+from vyos.vpp.config_deps import deps_bridge_dict
from vyos.vpp.config_deps import deps_xconnect_dict
from vyos.vpp.config_verify import (
verify_dev_driver,
@@ -254,6 +255,7 @@ def get_config(config=None):
)
xconn_members = deps_xconnect_dict(conf)
+ bridge_members = deps_bridge_dict(conf)
removed_ifaces = []
tmp = node_changed(conf, base_settings + ['interface'])
@@ -294,6 +296,7 @@ def get_config(config=None):
return {
'removed_ifaces': removed_ifaces,
'xconn_members': xconn_members,
+ 'bridge_members': bridge_members,
'persist_config': eth_ifaces_persist,
'interfaces_vpp': interfaces_config,
'remove': {},
@@ -433,6 +436,7 @@ def get_config(config=None):
if removed_ifaces:
config['removed_ifaces'] = removed_ifaces
config['xconn_members'] = xconn_members
+ config['bridge_members'] = bridge_members
config['interfaces_vpp'] = interfaces_config
@@ -611,32 +615,16 @@ def verify(config):
f'RX mode {rx_mode} is not supported for interface {iface}'
)
- # check GRE tunnels as part of the bridge, only tunnel-type teb is allowed
- # set vpp interfaces bridge br1 member interface vppgre1
- # set interfaces vpp gre vppgre1 tunnel-type teb
- if 'interfaces' in config:
- if 'bridge' in config['interfaces']:
- for iface, iface_config in config['interfaces']['bridge'].items():
- if 'member' in iface_config:
- for member in iface_config['member'].get('interface', []):
- if member.startswith('vppgre'):
- if (
- 'gre' in config['interfaces_vpp']
- and config['interfaces_vpp']['gre']
- .get(member, {})
- .get('tunnel_type')
- != 'teb'
- ):
- raise ConfigError(
- f'Only tunnel-type teb is allowed for GRE interfaces in bridge {iface}'
- )
-
- # Check if deleted interfaces are not xconnect memebrs
+ # Check if deleted interfaces are not xconnect members or not bridge members
for iface_config in config.get('removed_ifaces', []):
if iface_config['iface_name'] in config.get('xconn_members', {}):
raise ConfigError(
f'Interface {iface_config["iface_name"]} is an xconnect member and cannot be removed'
)
+ if iface_config['iface_name'] in config.get('bridge_members', {}):
+ raise ConfigError(
+ f'Interface {iface_config["iface_name"]} is a bridge member and cannot be removed'
+ )
verify_routes_count(config['settings'])
diff --git a/src/conf_mode/vpp_interfaces_bonding.py b/src/conf_mode/vpp_interfaces_bonding.py
index 89376ea32..553200832 100644
--- a/src/conf_mode/vpp_interfaces_bonding.py
+++ b/src/conf_mode/vpp_interfaces_bonding.py
@@ -24,7 +24,9 @@ from vyos.utils.assertion import assert_mac
from vyos.utils.process import is_systemd_service_active
from vyos.ifconfig.vpp import VPPBondInterface
+from vyos.vpp.config_deps import deps_bridge_dict
from vyos.vpp.config_deps import deps_xconnect_dict
+from vyos.vpp.config_verify import verify_vpp_remove_bridge_interface
from vyos.vpp.config_verify import verify_vpp_remove_xconnect_interface
from vyos.vpp.utils import cli_ifaces_list
@@ -96,6 +98,11 @@ def get_config(config=None) -> dict:
for xconn_iface in config['xconn_members'][ifname]:
set_dependents('vpp_interfaces_xconnect', conf, xconn_iface)
+ config['bridge_members'] = deps_bridge_dict(conf)
+ if ifname in config['bridge_members']:
+ for bridge_iface in config['bridge_members'][ifname]:
+ set_dependents('vpp_interfaces_bridge', conf, bridge_iface)
+
# NAT dependency
if conf.exists(['vpp', 'nat', 'nat44']):
set_dependents('vpp_nat_nat44', conf)
@@ -118,6 +125,7 @@ def verify(config):
return None
verify_vpp_remove_xconnect_interface(config)
+ verify_vpp_remove_bridge_interface(config)
if 'deleted' in config:
return None
diff --git a/src/conf_mode/vpp_interfaces_bridge.py b/src/conf_mode/vpp_interfaces_bridge.py
index edf3f2dd2..37cec7b94 100644
--- a/src/conf_mode/vpp_interfaces_bridge.py
+++ b/src/conf_mode/vpp_interfaces_bridge.py
@@ -16,13 +16,12 @@
# 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.configdict import node_changed
+from vyos.configdict import get_interface_dict
from vyos import ConfigError
-from vyos.vpp.interface import BridgeInterface
-from vyos.vpp.utils import iftunnel_transform
+from vyos.utils.process import is_systemd_service_active
+
+from vyos.ifconfig.vpp import VPPBridgeInterface
def get_config(config=None) -> dict:
@@ -38,65 +37,46 @@ def get_config(config=None) -> dict:
else:
conf = Config()
- base = ['vpp', 'interfaces', 'bridge']
- vpp_interfaces = ['vpp', 'settings', 'interface']
-
- ifname = os.environ['VYOS_TAGNODE_VALUE']
+ base = ['interfaces', 'vpp', 'bridge']
- # 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
- effective_config = conf.get_config_dict(
- base + [ifname],
+ # Get global vpp interfaces for verify
+ config['vpp_interfaces'] = conf.get_config_dict(
+ ['vpp', 'settings', 'interface'],
key_mangling=('-', '_'),
- effective=True,
get_first_key=True,
no_tag_node_value_mangle=True,
)
- if effective_config:
- config.update({'effective': effective_config})
-
- if not conf.exists(base + [ifname]):
- config['remove'] = True
-
- # Get global vpp interfaces for verify
- config['vpp_interfaces'] = conf.get_config_dict(
- vpp_interfaces,
+ # Get all gre interfaces config
+ config['gre_interfaces'] = conf.get_config_dict(
+ ['interfaces', 'vpp', 'gre'],
key_mangling=('-', '_'),
get_first_key=True,
no_tag_node_value_mangle=True,
+ with_defaults=True,
+ with_recursive_defaults=True,
)
- # determine which members have been removed
- interfaces_removed = node_changed(conf, base + [ifname, 'member', 'interface'])
- if interfaces_removed:
- config['members_removed'] = interfaces_removed
-
- 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
- # Check if interface exists in vpp before adding to bridge-domain
+ if not is_systemd_service_active('vpp.service'):
+ raise ConfigError(
+ 'Cannot configure VPP bridge interface: vpp.service is not running'
+ )
- allowed_prefixes = ('vppbond', 'vppgre', 'geneve', 'vpplo', 'vppvxlan')
+ # Check if interface exists in vpp before adding to bridge-domain
+ allowed_prefixes = ('vppbond', 'vppgre', 'vpplo', 'vppvxlan')
if 'member' in config:
bvi_exists = False
@@ -120,6 +100,18 @@ def verify(config):
raise ConfigError("BVI can only be defined on loopback interface")
bvi_exists = True
+ # check GRE tunnels as part of the bridge, only tunnel-type "teb" is allowed
+ # set interfaces vpp bridge vppbr1 member interface vppgre1
+ # set interfaces vpp gre vppgre1 tunnel-type teb
+ if member.startswith('vppgre'):
+ if member in config.get('gre_interfaces'):
+ gre_config = config.get('gre_interfaces').get(member)
+ if gre_config.get('tunnel_type') != 'teb':
+ raise ConfigError(
+ f'GRE interface "{member}" in bridge must have tunnel-type "teb". '
+ f'Current tunnel-type is "{gre_config.get("tunnel_type")}".'
+ )
+
def generate(config):
pass
@@ -130,54 +122,13 @@ def apply(config):
return None
ifname = config.get('ifname')
- # vppvxlan10 in the vpp is vxlan_tunnel10
- interface_transform_filter = ('geneve', 'vppvxlan')
- # update members
- if 'members_removed' in config:
- i = BridgeInterface(ifname)
- for member in config.get('members_removed'):
- if member.startswith(interface_transform_filter):
- member = iftunnel_transform(member)
- if member.startswith('vpplo'):
- # interface name in VPP is loopX
- member = member.replace('vpplo', 'loop')
- elif member.startswith('vppbond'):
- # interface name in VPP is BondEthernetX
- member = member.replace('vppbond', 'BondEthernet')
- i.detach_member(member=member)
-
- # Delete bridge domain
- if 'effective' in config:
- ifname = config.get('ifname')
- i = BridgeInterface(ifname)
- i.delete()
-
- if 'remove' in config:
- return None
+ bridge = VPPBridgeInterface(ifname)
+ bridge.remove()
+
+ if 'deleted' in config:
+ return
- # Add bridge domain
- members = config.get('member', {}).get('interface', '')
- i = BridgeInterface(ifname)
- i.add()
- # Add members to bridge
- if members:
- br = BridgeInterface(ifname)
- port_type = 0
- for member, member_config in members.items():
- if member.startswith(interface_transform_filter):
- member = iftunnel_transform(member)
- if member.startswith('vpplo'):
- # interface name in VPP is loopX
- member = member.replace('vpplo', 'loop')
- if 'bvi' in member_config:
- port_type = 1
- elif member.startswith('vppbond'):
- # interface name in VPP is BondEthernetX
- member = member.replace('vppbond', 'BondEthernet')
-
- br.add_member(member=member, port_type=port_type)
- # set default port type 0 (not BVI)
- port_type = 0
+ bridge.update(config)
return None
diff --git a/src/conf_mode/vpp_interfaces_gre.py b/src/conf_mode/vpp_interfaces_gre.py
index 453845bcf..1258f906c 100644
--- a/src/conf_mode/vpp_interfaces_gre.py
+++ b/src/conf_mode/vpp_interfaces_gre.py
@@ -24,11 +24,11 @@ from vyos.configdep import set_dependents, call_dependents
from vyos.utils.process import is_systemd_service_active
from vyos.ifconfig.vpp import VPPGREInterface
+from vyos.vpp.config_deps import deps_bridge_dict
from vyos.vpp.config_deps import deps_xconnect_dict
-from vyos.vpp.config_verify import (
- verify_vpp_remove_xconnect_interface,
- verify_vpp_tunnel_source_address,
-)
+from vyos.vpp.config_verify import verify_vpp_remove_bridge_interface
+from vyos.vpp.config_verify import verify_vpp_remove_xconnect_interface
+from vyos.vpp.config_verify import verify_vpp_tunnel_source_address
from vyos.vpp.utils import cli_ethernet_with_vifs_ifaces
@@ -62,6 +62,11 @@ def get_config(config=None) -> dict:
for xconn_iface in config['xconn_members'][ifname]:
set_dependents('vpp_interfaces_xconnect', conf, xconn_iface)
+ config['bridge_members'] = deps_bridge_dict(conf)
+ if ifname in config['bridge_members']:
+ for bridge_iface in config['bridge_members'][ifname]:
+ set_dependents('vpp_interfaces_bridge', conf, bridge_iface)
+
# Get 'vpp settings' config
config['vpp_settings'] = conf.get_config_dict(
['vpp', 'settings'],
@@ -99,6 +104,7 @@ def verify(config):
return None
verify_vpp_remove_xconnect_interface(config)
+ verify_vpp_remove_bridge_interface(config)
# config removed
if 'deleted' in config:
diff --git a/src/conf_mode/vpp_interfaces_vxlan.py b/src/conf_mode/vpp_interfaces_vxlan.py
index 9c24b6a01..38349cb4c 100644
--- a/src/conf_mode/vpp_interfaces_vxlan.py
+++ b/src/conf_mode/vpp_interfaces_vxlan.py
@@ -26,10 +26,9 @@ from vyos.utils.process import is_systemd_service_active
from vyos.ifconfig.vpp import VPPVXLANInterface
from vyos.vpp.config_deps import deps_bridge_dict
from vyos.vpp.config_deps import deps_xconnect_dict
-from vyos.vpp.config_verify import (
- verify_vpp_remove_xconnect_interface,
- verify_vpp_tunnel_source_address,
-)
+from vyos.vpp.config_verify import verify_vpp_remove_bridge_interface
+from vyos.vpp.config_verify import verify_vpp_remove_xconnect_interface
+from vyos.vpp.config_verify import verify_vpp_tunnel_source_address
from vyos.vpp.utils import cli_ethernet_with_vifs_ifaces
@@ -96,6 +95,7 @@ def verify(config):
return None
verify_vpp_remove_xconnect_interface(config)
+ verify_vpp_remove_bridge_interface(config)
if 'deleted' in config:
return None
diff --git a/src/migration-scripts/vpp/5-to-6 b/src/migration-scripts/vpp/5-to-6
index 03c20d970..0131dee33 100644
--- a/src/migration-scripts/vpp/5-to-6
+++ b/src/migration-scripts/vpp/5-to-6
@@ -47,6 +47,8 @@
#
# Migrate gre interface to 'interfaces vpp gre', remove interfaces with mode "point-to-multipoint" (T8325)
#
+# Migrate bridge interface from vpp section to 'interfaces vpp bridge' (T8327)
+#
from vyos.configtree import ConfigTree
@@ -496,6 +498,24 @@ def _migrate_vpp_gre_interface(config: ConfigTree) -> None:
config.delete(['vpp', 'interfaces'])
+def _migrate_vpp_bridge_interface(config: ConfigTree) -> None:
+ base = ['vpp', 'interfaces', 'bridge']
+ new_base = ['interfaces', 'vpp', 'bridge']
+
+ if not config.exists(base):
+ return
+
+ config.set(new_base)
+
+ for ifname in config.list_nodes(base):
+ _migrate_interface(config, 'bridge', 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
@@ -516,3 +536,4 @@ def migrate(config: ConfigTree) -> None:
_migrate_vpp_ipip_interface(config)
_migrate_vpp_loopback_interface(config)
_migrate_vpp_gre_interface(config)
+ _migrate_vpp_bridge_interface(config)
diff --git a/src/op_mode/vpp.py b/src/op_mode/vpp.py
index 868f780ae..54b46cf68 100755
--- a/src/op_mode/vpp.py
+++ b/src/op_mode/vpp.py
@@ -277,17 +277,17 @@ class VPPShow:
if ifname is None:
return None
- if not ifname.startswith('br') and not ifname[2:].isdigit():
+ if not ifname.startswith('vppbr') and not ifname[5:].isdigit():
raise vyos.opmode.IncorrectValue(
- f'"{ifname}" is not a valid bridge interface name (expected brN)'
+ f'"{ifname}" is not a valid bridge interface name (expected vppbrN)'
)
- if not self.config.exists(['vpp', 'interfaces', 'bridge', ifname]):
+ if not self.config.exists(['interfaces', 'vpp', 'bridge', ifname]):
raise vyos.opmode.IncorrectValue(
f'Bridge interface {ifname} does not exist'
)
- return int(ifname[2:])
+ return int(ifname[5:])
def _get_bridge_domain_raw(
self, bd_id: typing.Optional[int] = None
@@ -401,12 +401,12 @@ def show_lacp_details(raw: bool, ifname: typing.Optional[str]):
# -----------------------------
# Bridge op-mode entries
# -----------------------------
-@_verify('vpp interfaces bridge')
+@_verify('interfaces vpp bridge')
def show_bridge(raw: bool, ifname: typing.Optional[str] = None):
return VPPShow().bridge_domain(raw, ifname)
-@_verify('vpp interfaces bridge')
+@_verify('interfaces vpp bridge')
def show_bridge_details(raw: bool, ifname: typing.Optional[str] = None):
return VPPShow().bridge_domain_details(raw, ifname)