summaryrefslogtreecommitdiff
path: root/src/conf_mode/protocols_bgp.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/conf_mode/protocols_bgp.py')
-rwxr-xr-xsrc/conf_mode/protocols_bgp.py97
1 files changed, 72 insertions, 25 deletions
diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py
index 68284e0f9..cd46cbcb4 100755
--- a/src/conf_mode/protocols_bgp.py
+++ b/src/conf_mode/protocols_bgp.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020-2021 VyOS maintainers and contributors
+# Copyright (C) 2020-2022 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -138,13 +138,20 @@ def verify(bgp):
if asn == bgp['local_as']:
raise ConfigError('Cannot have local-as same as BGP AS number')
+ # Neighbor AS specified for local-as and remote-as can not be the same
+ if dict_search('remote_as', peer_config) == asn:
+ raise ConfigError(f'Neighbor "{peer}" has local-as specified which is '\
+ 'the same as remote-as, this is not allowed!')
+
# ttl-security and ebgp-multihop can't be used in the same configration
if 'ebgp_multihop' in peer_config and 'ttl_security' in peer_config:
raise ConfigError('You can not set both ebgp-multihop and ttl-security hops')
- # Check if neighbor has both override capability and strict capability match configured at the same time.
+ # Check if neighbor has both override capability and strict capability match
+ # configured at the same time.
if 'override_capability' in peer_config and 'strict_capability_match' in peer_config:
- raise ConfigError(f'Neighbor "{peer}" cannot have both override-capability and strict-capability-match configured at the same time!')
+ raise ConfigError(f'Neighbor "{peer}" cannot have both override-capability and '\
+ 'strict-capability-match configured at the same time!')
# Check spaces in the password
if 'password' in peer_config and ' ' in peer_config['password']:
@@ -157,15 +164,39 @@ def verify(bgp):
if not verify_remote_as(peer_config, bgp):
raise ConfigError(f'Neighbor "{peer}" remote-as must be set!')
+ # Peer-group member cannot override remote-as of peer-group
+ if 'peer_group' in peer_config:
+ peer_group = peer_config['peer_group']
+ if 'remote_as' in peer_config and 'remote_as' in bgp['peer_group'][peer_group]:
+ raise ConfigError(f'Peer-group member "{peer}" cannot override remote-as of peer-group "{peer_group}"!')
+ if 'interface' in peer_config:
+ if 'peer_group' in peer_config['interface']:
+ peer_group = peer_config['interface']['peer_group']
+ if 'remote_as' in peer_config['interface'] and 'remote_as' in bgp['peer_group'][peer_group]:
+ raise ConfigError(f'Peer-group member "{peer}" cannot override remote-as of peer-group "{peer_group}"!')
+ if 'v6only' in peer_config['interface']:
+ if 'peer_group' in peer_config['interface']['v6only']:
+ peer_group = peer_config['interface']['v6only']['peer_group']
+ if 'remote_as' in peer_config['interface']['v6only'] and 'remote_as' in bgp['peer_group'][peer_group]:
+ raise ConfigError(f'Peer-group member "{peer}" cannot override remote-as of peer-group "{peer_group}"!')
+
# Only checks for ipv4 and ipv6 neighbors
# Check if neighbor address is assigned as system interface address
- if is_ip(peer) and is_addr_assigned(peer):
- raise ConfigError(f'Can not configure a local address as neighbor "{peer}"')
+ vrf = None
+ vrf_error_msg = f' in default VRF!'
+ if 'vrf' in bgp:
+ vrf = bgp['vrf']
+ vrf_error_msg = f' in VRF "{vrf}"!'
+
+ if is_ip(peer) and is_addr_assigned(peer, vrf):
+ raise ConfigError(f'Can not configure local address as neighbor "{peer}"{vrf_error_msg}')
elif is_interface(peer):
if 'peer_group' in peer_config:
raise ConfigError(f'peer-group must be set under the interface node of "{peer}"')
if 'remote_as' in peer_config:
raise ConfigError(f'remote-as must be set under the interface node of "{peer}"')
+ if 'source_interface' in peer_config['interface']:
+ raise ConfigError(f'"source-interface" option not allowed for neighbor "{peer}"')
for afi in ['ipv4_unicast', 'ipv4_multicast', 'ipv4_labeled_unicast', 'ipv4_flowspec',
'ipv6_unicast', 'ipv6_multicast', 'ipv6_labeled_unicast', 'ipv6_flowspec',
@@ -183,6 +214,33 @@ def verify(bgp):
raise ConfigError(f'Neighbor "{peer}" cannot have both ipv6-unicast and ipv6-labeled-unicast configured at the same time!')
afi_config = peer_config['address_family'][afi]
+
+ if 'conditionally_advertise' in afi_config:
+ if 'advertise_map' not in afi_config['conditionally_advertise']:
+ raise ConfigError('Must speficy advertise-map when conditionally-advertise is in use!')
+ # Verify advertise-map (which is a route-map) exists
+ verify_route_map(afi_config['conditionally_advertise']['advertise_map'], bgp)
+
+ if ('exist_map' not in afi_config['conditionally_advertise'] and
+ 'non_exist_map' not in afi_config['conditionally_advertise']):
+ raise ConfigError('Must either speficy exist-map or non-exist-map when ' \
+ 'conditionally-advertise is in use!')
+
+ if {'exist_map', 'non_exist_map'} <= set(afi_config['conditionally_advertise']):
+ raise ConfigError('Can not specify both exist-map and non-exist-map for ' \
+ 'conditionally-advertise!')
+
+ if 'exist_map' in afi_config['conditionally_advertise']:
+ verify_route_map(afi_config['conditionally_advertise']['exist_map'], bgp)
+
+ if 'non_exist_map' in afi_config['conditionally_advertise']:
+ verify_route_map(afi_config['conditionally_advertise']['non_exist_map'], bgp)
+
+ # T4332: bgp deterministic-med cannot be disabled while addpath-tx-bestpath-per-AS is in use
+ if 'addpath_tx_per_as' in afi_config:
+ if dict_search('parameters.deterministic_med', bgp) == None:
+ raise ConfigError('addpath-tx-per-as requires BGP deterministic-med paramtere to be set!')
+
# Validate if configured Prefix list exists
if 'prefix_list' in afi_config:
for tmp in ['import', 'export']:
@@ -255,26 +313,16 @@ def verify(bgp):
tmp = dict_search(f'route_map.vpn.{export_import}', afi_config)
if tmp: verify_route_map(tmp, bgp)
- if afi in ['l2vpn_evpn'] and 'vrf' not in bgp:
- # Some L2VPN EVPN AFI options are only supported under VRF
- if 'vni' in afi_config:
- for vni, vni_config in afi_config['vni'].items():
- if 'rd' in vni_config:
- raise ConfigError('VNI route-distinguisher is only supported under EVPN VRF')
- if 'route_target' in vni_config:
- raise ConfigError('VNI route-target is only supported under EVPN VRF')
return None
def generate(bgp):
if not bgp or 'deleted' in bgp:
- bgp['frr_bgpd_config'] = ''
- bgp['frr_zebra_config'] = ''
return None
- bgp['protocol'] = 'bgp' # required for frr/vrf.route-map.frr.tmpl
- bgp['frr_zebra_config'] = render_to_string('frr/vrf.route-map.frr.tmpl', bgp)
- bgp['frr_bgpd_config'] = render_to_string('frr/bgpd.frr.tmpl', bgp)
+ bgp['protocol'] = 'bgp' # required for frr/vrf.route-map.frr.j2
+ bgp['frr_zebra_config'] = render_to_string('frr/vrf.route-map.frr.j2', bgp)
+ bgp['frr_bgpd_config'] = render_to_string('frr/bgpd.frr.j2', bgp)
return None
@@ -287,8 +335,9 @@ def apply(bgp):
# The route-map used for the FIB (zebra) is part of the zebra daemon
frr_cfg.load_configuration(zebra_daemon)
- frr_cfg.modify_section(r'(\s+)?ip protocol bgp route-map [-a-zA-Z0-9.]+$', '', '(\s|!)')
- frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', bgp['frr_zebra_config'])
+ frr_cfg.modify_section(r'(\s+)?ip protocol bgp route-map [-a-zA-Z0-9.]+', stop_pattern='(\s|!)')
+ if 'frr_zebra_config' in bgp:
+ frr_cfg.add_before(frr.default_add_before, bgp['frr_zebra_config'])
frr_cfg.commit_configuration(zebra_daemon)
# Generate empty helper string which can be ammended to FRR commands, it
@@ -298,13 +347,11 @@ def apply(bgp):
vrf = ' vrf ' + bgp['vrf']
frr_cfg.load_configuration(bgp_daemon)
- frr_cfg.modify_section(f'^router bgp \d+{vrf}$', '')
- frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', bgp['frr_bgpd_config'])
+ frr_cfg.modify_section(f'^router bgp \d+{vrf}', stop_pattern='^exit', remove_stop_mark=True)
+ if 'frr_bgpd_config' in bgp:
+ frr_cfg.add_before(frr.default_add_before, bgp['frr_bgpd_config'])
frr_cfg.commit_configuration(bgp_daemon)
- # Save configuration to /run/frr/config/frr.conf
- frr.save_configuration()
-
return None
if __name__ == '__main__':