summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/frr/bgpd.frr.j210
-rw-r--r--interface-definitions/include/bgp/protocol-common-config.xml.i30
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_bgp.py36
-rwxr-xr-xsrc/conf_mode/protocols_bgp.py43
4 files changed, 117 insertions, 2 deletions
diff --git a/data/templates/frr/bgpd.frr.j2 b/data/templates/frr/bgpd.frr.j2
index 3e101820c..9cfc8b7cd 100644
--- a/data/templates/frr/bgpd.frr.j2
+++ b/data/templates/frr/bgpd.frr.j2
@@ -565,3 +565,13 @@ bgp route-reflector allow-outbound-policy
timers bgp {{ timers.keepalive }} {{ timers.holdtime }}
{% endif %}
exit
+{% if interface is vyos_defined %}
+{% for iface, iface_config in interface.items() %}
+ interface {{ iface }}
+{% if iface_config.mpls.forwarding is vyos_defined %}
+ mpls bgp forwarding
+{% endif %}
+ exit
+ !
+{% endfor %}
+{% endif %}
diff --git a/interface-definitions/include/bgp/protocol-common-config.xml.i b/interface-definitions/include/bgp/protocol-common-config.xml.i
index d69fd7dab..f95031a75 100644
--- a/interface-definitions/include/bgp/protocol-common-config.xml.i
+++ b/interface-definitions/include/bgp/protocol-common-config.xml.i
@@ -873,6 +873,36 @@
</node>
</children>
</node>
+<tagNode name="interface">
+ <properties>
+ <help>Enable MPLS on Interface</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces</script>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>Interface name</description>
+ </valueHelp>
+ <constraint>
+ #include <include/constraint/interface-name.xml.i>
+ </constraint>
+ </properties>
+ <children>
+ <node name="mpls">
+ <properties>
+ <help> MPLS options</help>
+ </properties>
+ <children>
+ <leafNode name="forwarding">
+ <properties>
+ <help> Enable MPLS forwarding for eBGP directly connected peers</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+</tagNode>
<node name="listen">
<properties>
<help>Listen for and accept BGP dynamic neighbors from range</help>
diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py
index 2fd5d0c9b..f4801486a 100755
--- a/smoketest/scripts/cli/test_protocols_bgp.py
+++ b/smoketest/scripts/cli/test_protocols_bgp.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2021-2022 VyOS maintainers and contributors
+# Copyright (C) 2021-2023 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
@@ -18,6 +18,7 @@ import unittest
from base_vyostest_shim import VyOSUnitTestSHIM
+from vyos.ifconfig import Section
from vyos.configsession import ConfigSessionError
from vyos.template import is_ipv6
from vyos.util import process_named_running
@@ -1072,5 +1073,38 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
with self.assertRaises(ConfigSessionError):
self.cli_commit()
+ def test_bgp_22_interface_mpls_forwarding(self):
+ interfaces = Section.interfaces('ethernet')
+ self.cli_set(base_path + ['system-as', ASN])
+ for interface in interfaces:
+ self.cli_set(
+ base_path + ['interface', interface, 'mpls', 'forwarding'])
+ self.cli_commit()
+
+ for interface in interfaces:
+ frrconfig = self.getFRRconfig(f'interface {interface}')
+ self.assertIn(f'interface {interface}', frrconfig)
+ self.assertIn(f' mpls bgp forwarding', frrconfig)
+
+ def test_bgp_23_vrf_interface_mpls_forwarding(self):
+ self.create_bgp_instances_for_import_test()
+ interfaces = Section.interfaces('ethernet')
+ for interface in interfaces:
+ self.cli_set(
+ ['interfaces', 'ethernet', interface, 'vrf', import_vrf])
+ self.cli_set(
+ import_vrf_base + [import_vrf] + base_path + ['interface',
+ interface,
+ 'mpls',
+ 'forwarding'])
+ self.cli_commit()
+
+ for interface in interfaces:
+ frrconfig = self.getFRRconfig(f'interface {interface}')
+ self.assertIn(f'interface {interface}', frrconfig)
+ self.assertIn(f' mpls bgp forwarding', frrconfig)
+ self.cli_delete(['interfaces', 'ethernet', interface, 'vrf'])
+
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py
index b23584bdb..532970735 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-2022 VyOS maintainers and contributors
+# Copyright (C) 2020-2023 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
@@ -20,6 +20,7 @@ from sys import argv
from vyos.base import Warning
from vyos.config import Config
from vyos.configdict import dict_merge
+from vyos.configdict import node_changed
from vyos.configverify import verify_prefix_list
from vyos.configverify import verify_route_map
from vyos.configverify import verify_vrf
@@ -27,6 +28,7 @@ from vyos.template import is_ip
from vyos.template import is_interface
from vyos.template import render_to_string
from vyos.util import dict_search
+from vyos.util import get_interface_config
from vyos.validate import is_addr_assigned
from vyos import ConfigError
from vyos import frr
@@ -54,6 +56,20 @@ def get_config(config=None):
key_mangling=('-', '_'),
get_first_key=True,
no_tag_node_value_mangle=True)
+ # if config removed
+ interfaces_removed = node_changed(conf, base + ['interface'])
+ if interfaces_removed:
+ bgp['interface_removed'] = list(interfaces_removed)
+ # Add vrf mapping in <bgp interface ifname>
+ if 'interface' in bgp:
+ for interface in bgp['interface']:
+ tmp = get_interface_config(interface)
+ if dict_search('linkinfo.info_slave_kind', tmp) and \
+ tmp['linkinfo']['info_slave_kind'] == 'vrf':
+ if 'master' in tmp:
+ bgp['interface'][interface]['applied_vrf'] = tmp['master']
+ else:
+ bgp['interface'][interface]['applied_vrf'] = 'default'
# Assign the name of our VRF context. This MUST be done before the return
# statement below, else on deletion we will delete the default instance
@@ -231,6 +247,23 @@ def verify(bgp):
if 'system_as' not in bgp:
raise ConfigError('BGP system-as number must be defined!')
+ # Verify vrf on interface and bgp section
+ if 'interface' in bgp:
+ for interface in dict_search('interface', bgp):
+ if dict_search(f'interface.{interface}.mpls', bgp):
+ if 'forwarding' in bgp['interface'][interface]['mpls']:
+ if 'vrf' in bgp:
+ if bgp['interface'][interface]['applied_vrf'] != bgp['vrf']:
+ raise ConfigError(
+ f'Can not set mpls forwarding. Interface {interface} in different vrf')
+ else:
+ if bgp['interface'][interface]['applied_vrf'] != 'default':
+ raise ConfigError(
+ f'Can not set mpls forwarding. Interface {interface} in different vrf')
+ else:
+ raise ConfigError(
+ f'<protocols bgp interface {interface}> command should have options')
+
# Common verification for both peer-group and neighbor statements
for neighbor in ['neighbor', 'peer_group']:
# bail out early if there is no neighbor or peer-group statement
@@ -520,6 +553,14 @@ def apply(bgp):
vrf = ' vrf ' + bgp['vrf']
frr_cfg.load_configuration(bgp_daemon)
+
+ #If bgp interface config removed
+ for key in ['interface', 'interface_removed']:
+ if key not in bgp:
+ continue
+ for interface in bgp[key]:
+ frr_cfg.modify_section(f'^interface {interface}', stop_pattern='^exit', remove_stop_mark=True)
+
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'])