diff --git a/net/frr/pkg-descr b/net/frr/pkg-descr index 829df3bb5..1e52df4ba 100644 --- a/net/frr/pkg-descr +++ b/net/frr/pkg-descr @@ -14,6 +14,10 @@ Plugin Changelog 1.23 * Add route-reflector-client to BGP neighbor config +* bugfix: BGP Prefix List "IP version" field appears to be ineffective (#2602) +* feature: IPv6 link-local neighbors require an interface to be specified (#2604) +* feature: multiprotocol BGP sessions are not supported (#2606) +* bugfix: Multiple BGP peers causes config generation error (#2623) 1.22 diff --git a/net/frr/src/opnsense/mvc/app/controllers/OPNsense/Quagga/forms/dialogEditBGPNeighbor.xml b/net/frr/src/opnsense/mvc/app/controllers/OPNsense/Quagga/forms/dialogEditBGPNeighbor.xml index 3ae8d6830..f494060aa 100644 --- a/net/frr/src/opnsense/mvc/app/controllers/OPNsense/Quagga/forms/dialogEditBGPNeighbor.xml +++ b/net/frr/src/opnsense/mvc/app/controllers/OPNsense/Quagga/forms/dialogEditBGPNeighbor.xml @@ -26,7 +26,14 @@ neighbor.updatesource select_multiple - Physical name of the interface facing the peer + FRR documentation for more information.]]> + + + neighbor.linklocalinterface + + dropdown + true + FRR documentation for more information.]]> neighbor.nexthopself @@ -38,6 +45,13 @@ checkbox + + neighbor.multiprotocol + + checkbox + true + RFC 2283]]> + neighbor.rrclient diff --git a/net/frr/src/opnsense/mvc/app/controllers/OPNsense/Quagga/forms/dialogEditBGPPrefixLists.xml b/net/frr/src/opnsense/mvc/app/controllers/OPNsense/Quagga/forms/dialogEditBGPPrefixLists.xml index 115e015de..276e4e5d4 100644 --- a/net/frr/src/opnsense/mvc/app/controllers/OPNsense/Quagga/forms/dialogEditBGPPrefixLists.xml +++ b/net/frr/src/opnsense/mvc/app/controllers/OPNsense/Quagga/forms/dialogEditBGPPrefixLists.xml @@ -20,7 +20,7 @@ prefixlist.version - select_multiple + dropdown Set the IP version to use. @@ -32,7 +32,7 @@ prefixlist.action - select_multiple + dropdown Set permit for match or deny to negate the rule. diff --git a/net/frr/src/opnsense/mvc/app/models/OPNsense/Quagga/BGP.xml b/net/frr/src/opnsense/mvc/app/models/OPNsense/Quagga/BGP.xml index 767e8d008..cc5b2782b 100644 --- a/net/frr/src/opnsense/mvc/app/models/OPNsense/Quagga/BGP.xml +++ b/net/frr/src/opnsense/mvc/app/models/OPNsense/Quagga/BGP.xml @@ -66,6 +66,15 @@ /^(?!0).*$/ + + + N + N + Y + + /^(?!0).*$/ + + 0 N @@ -74,6 +83,10 @@ 0 N + + 0 + N + 0 N diff --git a/net/frr/src/opnsense/service/templates/OPNsense/Quagga/bgpd.conf b/net/frr/src/opnsense/service/templates/OPNsense/Quagga/bgpd.conf index 2505bb113..e0a9b8d5c 100644 --- a/net/frr/src/opnsense/service/templates/OPNsense/Quagga/bgpd.conf +++ b/net/frr/src/opnsense/service/templates/OPNsense/Quagga/bgpd.conf @@ -1,5 +1,31 @@ {% if helpers.exists('OPNsense.quagga.bgp.enabled') and OPNsense.quagga.bgp.enabled == '1' %} -{% from 'OPNsense/Macros/interface.macro' import physical_interface %} +{% from 'OPNsense/Macros/interface.macro' import physical_interface %} +{% set addressFamilies = ['ipv4', 'ipv6' ] %} +{% set neighbors = {'ipv4': [], 'ipv6': []} %} +{% set networks = {'ipv4': [], 'ipv6': []} %} + +{% if helpers.exists('OPNsense.quagga.bgp.neighbors.neighbor') %} +{% for neighbor in helpers.toList('OPNsense.quagga.bgp.neighbors.neighbor') %} +{% if neighbor.enabled == '1' and neighbor.multiprotocol == '1' %} +{# // the .append() method in Jinja2 returns "None", so filter through default() to suppress #} +{{ neighbors['ipv4'].append(neighbor) | default("", True) }} +{{ neighbors['ipv6'].append(neighbor) | default("", True) }} +{% elif neighbor.enabled == '1' and ':' not in neighbor.address %} +{{ neighbors['ipv4'].append(neighbor) | default("", True) }} +{% elif neighbor.enabled == '1' and ':' in neighbor.address %} +{{ neighbors['ipv6'].append(neighbor) | default("", True) }} +{% endif %} +{% endfor %} +{% endif %} +{% if helpers.exists('OPNsense.quagga.bgp.networks') %} +{% for network in OPNsense.quagga.bgp.networks.split(',') %} +{% if ':' not in network %} +{{ networks['ipv4'].append(network) | default("", True) }} +{% elif ':' in network %} +{{ networks['ipv6'].append(network) | default("", True) }} +{% endif %} +{% endfor %} +{% endif %} ! ! Zebra configuration saved from vty ! 2017/03/03 20:21:04 @@ -31,9 +57,12 @@ router bgp {{ OPNsense.quagga.bgp.asnumber }} {% if 'bfd' in neighbor and neighbor.bfd == '1' %} neighbor {{ neighbor.address }} bfd {% endif %} - {% if 'updatesource' in neighbor and neighbor.updatesource != '' %} +{% if ':' not in neighbor.address and 'updatesource' in neighbor and neighbor.updatesource != '' %} neighbor {{ neighbor.address }} update-source {{ physical_interface(neighbor.updatesource) }} {% endif %} +{% if ':' in neighbor.address and 'linklocalinterface' in neighbor and neighbor.linklocalinterface != '' %} + neighbor {{ neighbor.address }} interface {{ physical_interface(neighbor.linklocalinterface) }} +{% endif %} {% if 'multihop' in neighbor and neighbor.multihop == '1' %} neighbor {{ neighbor.address }} ebgp-multihop {% endif %} @@ -48,145 +77,72 @@ router bgp {{ OPNsense.quagga.bgp.asnumber }} {% endif %} {% endfor %} {% endif %} - address-family ipv4 unicast -{% if helpers.exists('OPNsense.quagga.bgp.networks') %} -{% for network in OPNsense.quagga.bgp.networks.split(',') %} -{% if ':' not in network %} - network {{ network }} -{% endif %} -{% endfor %} -{% endif %} + +{% for addressFamily in addressFamilies %} + address-family {{ addressFamily }} unicast {% if helpers.exists('OPNsense.quagga.bgp.redistribute') and OPNsense.quagga.bgp.redistribute != '' %} {% for bgp_redistribute in OPNsense.quagga.bgp.redistribute.split(',') %} redistribute {{ bgp_redistribute }} {% endfor %} {% endif %} -{% if helpers.exists('OPNsense.quagga.bgp.neighbors.neighbor') and ':' not in OPNsense.quagga.bgp.neighbors.neighbor.address %} -{% for neighbor in helpers.toList('OPNsense.quagga.bgp.neighbors.neighbor') %} -{% if neighbor.enabled == '1' and ':' not in neighbor.address %} -{% if 'nexthopself' in neighbor and neighbor.nexthopself == '1' %} - neighbor {{ neighbor.address }} next-hop-self -{% endif %} -{% if 'rrclient' in neighbor and neighbor.rrclient == '1' %} - neighbor {{ neighbor.address }} route-reflector-client -{% endif %} -{% if 'defaultoriginate' in neighbor and neighbor.defaultoriginate == '1' %} - neighbor {{ neighbor.address }} default-originate -{% endif %} -{% if neighbor.linkedPrefixlistIn|default("") != "" %} -{% for prefixlist in neighbor.linkedPrefixlistIn.split(",") %} -{% set prefixlist2_data = helpers.getUUID(prefixlist) %} -{% if prefixlist2_data != {} and prefixlist2_data.enabled == '1' %} - neighbor {{ neighbor.address }} prefix-list {{ prefixlist2_data.name }} in -{% endif %} -{% endfor %} -{% endif %} -{% if neighbor.linkedPrefixlistOut|default("") != "" %} -{% for prefixlist in neighbor.linkedPrefixlistOut.split(",") %} -{% set prefixlist_data = helpers.getUUID(prefixlist) %} -{% if prefixlist_data != {} and prefixlist_data.enabled == '1' %} - neighbor {{ neighbor.address }} prefix-list {{ prefixlist_data.name }} out -{% endif %} -{% endfor %} -{% endif %} -{% if neighbor.linkedRoutemapIn|default("") != "" %} -{% for aspath in neighbor.linkedRoutemapIn.split(",") %} -{% set routemap2_data = helpers.getUUID(aspath) %} -{% if routemap2_data != {} and routemap2_data.enabled == '1' %} - neighbor {{ neighbor.address }} route-map {{ routemap2_data.name }} in -{% endif %} -{% endfor %} -{% endif %} -{% if neighbor.linkedRoutemapOut|default("") != "" %} -{% for aspath in neighbor.linkedRoutemapOut.split(",") %} -{% set routemap_data = helpers.getUUID(aspath) %} -{% if routemap_data != {} and routemap_data.enabled == '1' %} - neighbor {{ neighbor.address }} route-map {{ routemap_data.name }} out -{% endif %} -{% endfor %} -{% endif %} -{% endif %} -{% endfor %} -{% endif %} -{% if helpers.exists('OPNsense.quagga.bgp.neighbors.neighbor') %} -{% for neighbor in helpers.toList('OPNsense.quagga.bgp.neighbors.neighbor') %} -{% if neighbor.enabled == '1' and ':' in neighbor.address %} - no neighbor {{ neighbor.address }} activate -{% endif %} -{% endfor %} -{% endif %} - exit-address-family -! - address-family ipv6 unicast -{% if helpers.exists('OPNsense.quagga.bgp.networks') and ':' in OPNsense.quagga.bgp.networks %} -{% for network in OPNsense.quagga.bgp.networks.split(',') %} -{% if ':' in network %} +{% for network in networks[addressFamily] %} network {{ network }} -{% endif %} -{% endfor %} -{% endif %} -{% if helpers.exists('OPNsense.quagga.bgp.redistribute') and OPNsense.quagga.bgp.redistribute != '' %} -{% for bgp_redistribute in OPNsense.quagga.bgp.redistribute.split(',') %} - redistribute {{ bgp_redistribute }} -{% endfor %} -{% endif %} -{% if helpers.exists('OPNsense.quagga.bgp.neighbors.neighbor') %} -{% for neighbor in helpers.toList('OPNsense.quagga.bgp.neighbors.neighbor') %} -{% if neighbor.enabled == '1' and ':' in neighbor.address %} +{% endfor %} +{% for neighbor in neighbors[addressFamily] %} neighbor {{ neighbor.address }} activate -{% if 'nexthopself' in neighbor and neighbor.nexthopself == '1' %} +{% if 'nexthopself' in neighbor and neighbor.nexthopself == '1' %} neighbor {{ neighbor.address }} next-hop-self -{% endif %} -{% if 'rrclient' in neighbor and neighbor.rrclient == '1' %} +{% endif %} +{% if 'rrclient' in neighbor and neighbor.rrclient == '1' %} neighbor {{ neighbor.address }} route-reflector-client -{% endif %} -{% if 'defaultoriginate' in neighbor and neighbor.defaultoriginate == '1' %} +{% endif %} +{% if 'defaultoriginate' in neighbor and neighbor.defaultoriginate == '1' %} neighbor {{ neighbor.address }} default-originate -{% endif %} -{% if neighbor.linkedPrefixlistIn|default("") != "" %} -{% for prefixlist in neighbor.linkedPrefixlistIn.split(",") %} -{% set prefixlist2_data = helpers.getUUID(prefixlist) %} -{% if prefixlist2_data != {} and prefixlist2_data.enabled == '1' %} +{% endif %} +{% if neighbor.linkedPrefixlistIn|default("") != "" %} +{% for prefixlist in neighbor.linkedPrefixlistIn.split(",") %} +{% set prefixlist2_data = helpers.getUUID(prefixlist) %} +{% if prefixlist2_data != {} and prefixlist2_data.enabled == '1' %} neighbor {{ neighbor.address }} prefix-list {{ prefixlist2_data.name }} in -{% endif %} -{% endfor %} {% endif %} -{% if neighbor.linkedPrefixlistOut|default("") != "" %} -{% for prefixlist in neighbor.linkedPrefixlistOut.split(",") %} -{% set prefixlist_data = helpers.getUUID(prefixlist) %} -{% if prefixlist_data != {} and prefixlist_data.enabled == '1' %} +{% endfor %} +{% endif %} +{% if neighbor.linkedPrefixlistOut|default("") != "" %} +{% for prefixlist in neighbor.linkedPrefixlistOut.split(",") %} +{% set prefixlist_data = helpers.getUUID(prefixlist) %} +{% if prefixlist_data != {} and prefixlist_data.enabled == '1' %} neighbor {{ neighbor.address }} prefix-list {{ prefixlist_data.name }} out -{% endif %} -{% endfor %} {% endif %} -{% if neighbor.linkedRoutemapIn|default("") != "" %} -{% for aspath in neighbor.linkedRoutemapIn.split(",") %} -{% set routemap2_data = helpers.getUUID(aspath) %} -{% if routemap2_data != {} and routemap2_data.enabled == '1' %} +{% endfor %} +{% endif %} +{% if neighbor.linkedRoutemapIn|default("") != "" %} +{% for aspath in neighbor.linkedRoutemapIn.split(",") %} +{% set routemap2_data = helpers.getUUID(aspath) %} +{% if routemap2_data != {} and routemap2_data.enabled == '1' %} neighbor {{ neighbor.address }} route-map {{ routemap2_data.name }} in -{% endif %} -{% endfor %} {% endif %} -{% if neighbor.linkedRoutemapOut|default("") != "" %} -{% for aspath in neighbor.linkedRoutemapOut.split(",") %} -{% set routemap_data = helpers.getUUID(aspath) %} -{% if routemap_data != {} and routemap_data.enabled == '1' %} +{% endfor %} +{% endif %} +{% if neighbor.linkedRoutemapOut|default("") != "" %} +{% for aspath in neighbor.linkedRoutemapOut.split(",") %} +{% set routemap_data = helpers.getUUID(aspath) %} +{% if routemap_data != {} and routemap_data.enabled == '1' %} neighbor {{ neighbor.address }} route-map {{ routemap_data.name }} out -{% endif %} -{% endfor %} {% endif %} -{% endif %} -{% endfor %} -{% endif %} +{% endfor %} +{% endif %} +{% endfor %} exit-address-family ! +{% endfor %} + {% if helpers.exists('OPNsense.quagga.bgp.prefixlists.prefixlist') %} {% for prefixlist in helpers.sortDictList(OPNsense.quagga.bgp.prefixlists.prefixlist, 'name', 'seqnumber' ) %} -{% if prefixlist.enabled == '1' and ':' not in prefixlist.network %} +{% if prefixlist.enabled == '1' and prefixlist.version == 'IPv4' %} ip prefix-list {{ prefixlist.name }} seq {{ prefixlist.seqnumber }} {{ prefixlist.action }} {{ prefixlist.network }} {% endif %} ! -{% if prefixlist.enabled == '1' and ':' in prefixlist.network %} +{% if prefixlist.enabled == '1' and prefixlist.version == 'IPv6' %} ipv6 prefix-list {{ prefixlist.name }} seq {{ prefixlist.seqnumber }} {{ prefixlist.action }} {{ prefixlist.network }} {% endif %} {% endfor %}