summaryrefslogtreecommitdiff
path: root/data/templates/frr/bgpd.frr.tmpl
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2021-05-08 21:21:21 +0200
committerChristian Poessinger <christian@poessinger.com>2021-05-08 22:49:42 +0200
commit1d9cf31e849b862063200309734bab6620f57f1d (patch)
tree21b40ddd787447d6fb452dcf58256a28027d8522 /data/templates/frr/bgpd.frr.tmpl
parentb5c608949719f4fcbf4234a0e8e52e5d7692b362 (diff)
downloadvyos-1x-1d9cf31e849b862063200309734bab6620f57f1d.tar.gz
vyos-1x-1d9cf31e849b862063200309734bab6620f57f1d.zip
vrf: bgp: T3523: bugfix Kernel route-map deployment
Commit 4f9aa30f ("vrf: bgp: T3523: add route-map support for kernel routes") added the possibility to also filter BGP routes towards the OS kernel, but the smoketests failed. Reason was a non working CLI command applied to bgpd. Thus the VRF route-map and the BGP configuration is now split into two templates, one to be used for each daemon (zebra and bgpd). Nevertheless one more bug was found in vyos.frr which currently does not suppoort calling modify_section() inside a configuration "block". See [1] for more info. [1]: https://phabricator.vyos.net/T3529
Diffstat (limited to 'data/templates/frr/bgpd.frr.tmpl')
-rw-r--r--data/templates/frr/bgpd.frr.tmpl473
1 files changed, 473 insertions, 0 deletions
diff --git a/data/templates/frr/bgpd.frr.tmpl b/data/templates/frr/bgpd.frr.tmpl
new file mode 100644
index 000000000..57b9ba8d6
--- /dev/null
+++ b/data/templates/frr/bgpd.frr.tmpl
@@ -0,0 +1,473 @@
+{### MACRO definition for recurring peer patter, this can be either fed by a ###}
+{### peer-group or an individual BGP neighbor ###}
+{% macro bgp_neighbor(neighbor, config, peer_group=false) %}
+{% if peer_group == true %}
+ neighbor {{ neighbor }} peer-group
+{% elif config.peer_group is defined and config.peer_group is not none %}
+ neighbor {{ neighbor }} peer-group {{ config.peer_group }}
+{% endif %}
+{% if config.remote_as is defined and config.remote_as is not none %}
+ neighbor {{ neighbor }} remote-as {{ config.remote_as }}
+{% endif %}
+{% if config.interface is defined and config.interface.remote_as is defined and config.interface.remote_as is not none %}
+ neighbor {{ neighbor }} interface remote-as {{ config.interface.remote_as }}
+{% endif %}
+{% if config.advertisement_interval is defined and config.advertisement_interval is not none %}
+ neighbor {{ neighbor }} advertisement-interval {{ config.advertisement_interval }}
+{% endif %}
+{% if config.bfd is defined %}
+ neighbor {{ neighbor }} bfd
+{% endif %}
+{% if config.capability is defined and config.capability is not none %}
+{% if config.capability.dynamic is defined %}
+ neighbor {{ neighbor }} capability dynamic
+{% endif %}
+{% if config.capability.extended_nexthop is defined %}
+ neighbor {{ neighbor }} capability extended-nexthop
+{% endif %}
+{% endif %}
+{% if config.description is defined and config.description is not none %}
+ neighbor {{ neighbor }} description {{ config.description }}
+{% endif %}
+{% if config.disable_capability_negotiation is defined %}
+ neighbor {{ neighbor }} dont-capability-negotiate
+{% endif %}
+{% if config.ebgp_multihop is defined and config.ebgp_multihop is not none %}
+ neighbor {{ neighbor }} ebgp-multihop {{ config.ebgp_multihop }}
+{% endif %}
+{% if config.graceful_restart is defined and config.graceful_restart is not none %}
+{% if config.graceful_restart == 'enable' %}
+{% set graceful_restart = 'graceful-restart' %}
+{% elif config.graceful_restart == 'disable' %}
+{% set graceful_restart = 'graceful-restart-disable' %}
+{% elif config.graceful_restart == 'restart-helper' %}
+{% set graceful_restart = 'graceful-restart-helper' %}
+{% endif %}
+ neighbor {{ neighbor }} {{ graceful_restart }}
+{% endif %}
+{% if config.local_as is defined and config.local_as is not none %}
+{% for local_asn in config.local_as %}
+ neighbor {{ neighbor }} local-as {{ local_asn }} {{ 'no-prepend' if config.local_as[local_asn].no_prepend is defined }}
+{% endfor %}
+{% endif %}
+{% if config.override_capability is defined %}
+ neighbor {{ neighbor }} override-capability
+{% endif %}
+{% if config.passive is defined %}
+ neighbor {{ neighbor }} passive
+{% endif %}
+{% if config.password is defined and config.password is not none %}
+ neighbor {{ neighbor }} password {{ config.password }}
+{% endif %}
+{% if config.port is defined and config.port is not none %}
+ neighbor {{ neighbor }} port {{ config.port }}
+{% endif %}
+{% if config.shutdown is defined %}
+ neighbor {{ neighbor }} shutdown
+{% endif %}
+{% if config.strict_capability_match is defined %}
+ neighbor {{ neighbor }} strict-capability-match
+{% endif %}
+{% if config.ttl_security is defined and config.ttl_security.hops is defined and config.ttl_security.hops is not none %}
+ neighbor {{ neighbor }} ttl-security hops {{ config.ttl_security.hops }}
+{% endif %}
+{% if config.timers is defined %}
+{% if config.timers.connect is defined and config.timers.connect is not none %}
+ neighbor {{ neighbor }} timers connect {{ config.timers.connect }}
+{% endif %}
+{% if config.timers.holdtime is defined and config.timers.keepalive is defined and config.timers.holdtime is not none and config.timers.keepalive is not none %}
+ neighbor {{ neighbor }} timers {{ config.timers.keepalive }} {{ config.timers.holdtime }}
+{% endif %}
+{% endif %}
+{% if config.update_source is defined and config.update_source is not none %}
+ neighbor {{ neighbor }} update-source {{ config.update_source }}
+{% endif %}
+{% if config.interface is defined and config.interface is not none %}
+{% if config.interface.peer_group is defined and config.interface.peer_group is not none %}
+ neighbor {{ neighbor }} interface peer-group {{ config.interface.peer_group }}
+{% endif %}
+{% if config.interface.v6only is defined and config.interface.v6only is not none %}
+{% if config.interface.v6only.peer_group is defined and config.interface.v6only.peer_group is not none %}
+ neighbor {{ neighbor }} interface v6only peer-group {{ config.interface.v6only.peer_group }}
+{% endif %}
+{% if config.interface.v6only.remote_as is defined and config.interface.v6only.remote_as is not none %}
+ neighbor {{ neighbor }} interface v6only remote-as {{ config.interface.v6only.remote_as }}
+{% endif %}
+{% endif %}
+{% endif %}
+ !
+{% if config.address_family is defined and config.address_family is not none %}
+{% for afi, afi_config in config.address_family.items() %}
+{% if afi == 'ipv4_unicast' %}
+ address-family ipv4 unicast
+{% elif afi == 'ipv4_multicast' %}
+ address-family ipv4 multicast
+{% elif afi == 'ipv4_labeled_unicast' %}
+ address-family ipv4 labeled-unicast
+{% elif afi == 'ipv4_vpn' %}
+ address-family ipv4 vpn
+{% elif afi == 'ipv4_flowspec' %}
+ address-family ipv4 flowspec
+{% elif afi == 'ipv6_unicast' %}
+ address-family ipv6 unicast
+{% elif afi == 'ipv6_multicast' %}
+ address-family ipv6 multicast
+{% elif afi == 'ipv6_labeled_unicast' %}
+ address-family ipv6 labeled-unicast
+{% elif afi == 'ipv6_vpn' %}
+ address-family ipv6 vpn
+{% elif afi == 'ipv6_flowspec' %}
+ address-family ipv6 flowspec
+{% elif afi == 'l2vpn_evpn' %}
+ address-family l2vpn evpn
+{% endif %}
+{% if afi_config.addpath_tx_all is defined %}
+ neighbor {{ neighbor }} addpath-tx-all-paths
+{% endif %}
+{% if afi_config.addpath_tx_per_as is defined %}
+ neighbor {{ neighbor }} addpath-tx-bestpath-per-AS
+{% endif %}
+{% if afi_config.allowas_in is defined and afi_config.allowas_in is not none %}
+ neighbor {{ neighbor }} allowas-in {{ afi_config.allowas_in.number if afi_config.allowas_in.number is defined }}
+{% endif %}
+{% if afi_config.as_override is defined %}
+ neighbor {{ neighbor }} as-override
+{% endif %}
+{% if afi_config.remove_private_as is defined %}
+ neighbor {{ neighbor }} remove-private-AS
+{% endif %}
+{% if afi_config.route_reflector_client is defined %}
+ neighbor {{ neighbor }} route-reflector-client
+{% endif %}
+{% if afi_config.weight is defined and afi_config.weight is not none %}
+ neighbor {{ neighbor }} weight {{ afi_config.weight }}
+{% endif %}
+{% if afi_config.attribute_unchanged is defined and afi_config.attribute_unchanged is not none %}
+ neighbor {{ neighbor }} attribute-unchanged {{ 'as-path ' if afi_config.attribute_unchanged.as_path is defined }}{{ 'med ' if afi_config.attribute_unchanged.med is defined }}{{ 'next-hop ' if afi_config.attribute_unchanged.next_hop is defined }}
+{% endif %}
+{% if afi_config.capability is defined and afi_config.capability.orf is defined and afi_config.capability.orf.prefix_list is defined and afi_config.capability.orf.prefix_list.send is defined %}
+ neighbor {{ neighbor }} capability orf prefix-list send
+{% endif %}
+{% if afi_config.capability is defined and afi_config.capability.orf is defined and afi_config.capability.orf.prefix_list is defined and afi_config.capability.orf.prefix_list.receive is defined %}
+ neighbor {{ neighbor }} capability orf prefix-list receive
+{% endif %}
+{% if afi_config.default_originate is defined %}
+ neighbor {{ neighbor }} default-originate {{ 'route-map ' ~ afi_config.default_originate.route_map if afi_config.default_originate.route_map is defined }}
+{% endif %}
+{% if afi_config.distribute_list is defined and afi_config.distribute_list is not none %}
+{% if afi_config.distribute_list.export is defined and afi_config.distribute_list.export is not none %}
+ neighbor {{ neighbor }} distribute-list {{ afi_config.distribute_list.export }} out
+{% endif %}
+{% if afi_config.distribute_list.import is defined and afi_config.distribute_list.import is not none %}
+ neighbor {{ neighbor }} distribute-list {{ afi_config.distribute_list.import }} in
+{% endif %}
+{% endif %}
+{% if afi_config.filter_list is defined and afi_config.filter_list is not none %}
+{% if afi_config.filter_list.export is defined and afi_config.filter_list.export is not none %}
+ neighbor {{ neighbor }} filter-list {{ afi_config.filter_list.export }} out
+{% endif %}
+{% if afi_config.filter_list.import is defined and afi_config.filter_list.import is not none %}
+ neighbor {{ neighbor }} filter-list {{ afi_config.filter_list.import }} in
+{% endif %}
+{% endif %}
+{% if afi_config.maximum_prefix is defined and afi_config.maximum_prefix is not none %}
+ neighbor {{ neighbor }} maximum-prefix {{ afi_config.maximum_prefix }}
+{% endif %}
+{% if afi_config.nexthop_self is defined %}
+ neighbor {{ neighbor }} next-hop-self {{ 'force' if afi_config.nexthop_self.force is defined }}
+{% endif %}
+{% if afi_config.route_server_client is defined %}
+ neighbor {{ neighbor }} route-server-client
+{% endif %}
+{% if afi_config.route_map is defined and afi_config.route_map is not none %}
+{% if afi_config.route_map.export is defined and afi_config.route_map.export is not none %}
+ neighbor {{ neighbor }} route-map {{ afi_config.route_map.export }} out
+{% endif %}
+{% if afi_config.route_map.import is defined and afi_config.route_map.import is not none %}
+ neighbor {{ neighbor }} route-map {{ afi_config.route_map.import }} in
+{% endif %}
+{% endif %}
+{% if afi_config.prefix_list is defined and afi_config.prefix_list is not none %}
+{% if afi_config.prefix_list.export is defined and afi_config.prefix_list.export is not none %}
+ neighbor {{ neighbor }} prefix-list {{ afi_config.prefix_list.export }} out
+{% endif %}
+{% if afi_config.prefix_list.import is defined and afi_config.prefix_list.import is not none %}
+ neighbor {{ neighbor }} prefix-list {{ afi_config.prefix_list.import }} in
+{% endif %}
+{% endif %}
+{% if afi_config.soft_reconfiguration is defined and afi_config.soft_reconfiguration.inbound is defined %}
+ neighbor {{ neighbor }} soft-reconfiguration inbound
+{% endif %}
+{% if afi_config.unsuppress_map is defined and afi_config.unsuppress_map is not none %}
+ neighbor {{ neighbor }} unsuppress-map {{ afi_config.unsuppress_map }}
+{% endif %}
+{% if afi_config.disable_send_community is defined and afi_config.disable_send_community.extended is defined %}
+ no neighbor {{ neighbor }} send-community extended
+{% endif %}
+{% if afi_config.disable_send_community is defined and afi_config.disable_send_community.standard is defined %}
+ no neighbor {{ neighbor }} send-community standard
+{% endif %}
+ neighbor {{ neighbor }} activate
+ exit-address-family
+ !
+{% endfor %}
+{% endif %}
+{% endmacro %}
+!
+router bgp {{ local_as }} {{ 'vrf ' ~ vrf if vrf is defined and vrf is not none }}
+{% if parameters is defined and parameters.ebgp_requires_policy is defined %}
+ bgp ebgp-requires-policy
+{% else %}
+ no bgp ebgp-requires-policy
+{% endif %}
+{% if parameters is defined and parameters.default is defined and parameters.default.no_ipv4_unicast is defined %}
+{# Option must be set before any neighbor - see https://phabricator.vyos.net/T3463 #}
+ no bgp default ipv4-unicast
+{% endif %}
+{# Workaround for T2100 until we have decided about a migration script #}
+ no bgp network import-check
+{% if address_family is defined and address_family is not none %}
+{% for afi, afi_config in address_family.items() %}
+ !
+{% if afi == 'ipv4_unicast' %}
+ address-family ipv4 unicast
+{% elif afi == 'ipv4_multicast' %}
+ address-family ipv4 multicast
+{% elif afi == 'ipv4_labeled_unicast' %}
+ address-family ipv4 labeled-unicast
+{% elif afi == 'ipv4_vpn' %}
+ address-family ipv4 vpn
+{% elif afi == 'ipv4_flowspec' %}
+ address-family ipv4 flowspec
+{% elif afi == 'ipv6_unicast' %}
+ address-family ipv6 unicast
+{% elif afi == 'ipv6_multicast' %}
+ address-family ipv6 multicast
+{% elif afi == 'ipv6_labeled_unicast' %}
+ address-family ipv6 labeled-unicast
+{% elif afi == 'ipv6_vpn' %}
+ address-family ipv6 vpn
+{% elif afi == 'ipv6_flowspec' %}
+ address-family ipv6 flowspec
+{% elif afi == 'l2vpn_evpn' %}
+ address-family l2vpn evpn
+{% endif %}
+{% if afi_config.aggregate_address is defined and afi_config.aggregate_address is not none %}
+{% for ip in afi_config.aggregate_address %}
+ aggregate-address {{ ip }}{{ ' as-set' if afi_config.aggregate_address[ip].as_set is defined }}{{ ' summary-only' if afi_config.aggregate_address[ip].summary_only is defined }}
+{% endfor %}
+{% endif %}
+{% if afi_config.maximum_paths is defined and afi_config.maximum_paths.ebgp is defined and afi_config.maximum_paths.ebgp is not none %}
+ maximum-paths {{ afi_config.maximum_paths.ebgp }}
+{% endif %}
+{% if afi_config.maximum_paths is defined and afi_config.maximum_paths.ibgp is defined and afi_config.maximum_paths.ibgp is not none %}
+ maximum-paths ibgp {{ afi_config.maximum_paths.ibgp }}
+{% endif %}
+{% if afi_config.redistribute is defined and afi_config.redistribute is not none %}
+{% for protocol in afi_config.redistribute %}
+{% if protocol == 'table' %}
+ redistribute table {{ afi_config.redistribute[protocol].table }}
+{% else %}
+{% set redistribution_protocol = protocol %}
+{% if protocol == 'ospfv3' %}
+{% set redistribution_protocol = 'ospf6' %}
+{% endif %}
+ redistribute {{ redistribution_protocol }}{% if afi_config.redistribute[protocol].metric is defined %} metric {{ afi_config.redistribute[protocol].metric }}{% endif %}{% if afi_config.redistribute[protocol].route_map is defined %} route-map {{ afi_config.redistribute[protocol].route_map }}{% endif %}
+{####### we need this blank line!! #######}
+
+{% endif %}
+{% endfor %}
+{% endif %}
+{% if afi_config.network is defined and afi_config.network is not none %}
+{% for network in afi_config.network %}
+ network {{ network }}{% if afi_config.network[network].route_map is defined %} route-map {{ afi_config.network[network].route_map }}{% endif %}{% if afi_config.network[network].backdoor is defined %} backdoor{% endif %}{% if afi_config.network[network].rd is defined and afi_config.network[network].label is defined%} rd {{ afi_config.network[network].rd }} label {{ afi_config.network[network].label }}{% endif %}
+{####### we need this blank line!! #######}
+
+{% endfor %}
+{% endif %}
+{% if afi_config.advertise is defined and afi_config.advertise is not none %}
+{% for adv_afi, adv_afi_config in afi_config.advertise.items() %}
+{% if adv_afi_config.unicast is defined and adv_afi_config.unicast is not none %}
+ advertise {{ adv_afi }} unicast {{ 'route-map ' ~ adv_afi_config.unicast.route_map if adv_afi_config.unicast.route_map is defined }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% if afi_config.distance is defined and afi_config.distance is not none %}
+{% if afi_config.distance is defined and afi_config.distance.external is defined and afi_config.distance.internal is defined and afi_config.distance.local is defined %}
+ distance bgp {{ afi_config.distance.external }} {{ afi_config.distance.internal }} {{ afi_config.distance.local }}
+{% endif %}
+{% if afi_config.distance.prefix is defined and afi_config.distance.prefix is not none %}
+{% for prefix in afi_config.distance.prefix %}
+ distance {{ afi_config.distance.prefix[prefix].distance }} {{ prefix }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{% if afi_config.local_install is defined and afi_config.local_install is not none %}
+{% for interface in afi_config.local_install.interface %}
+ local-install {{ interface }}
+{% endfor %}
+{% endif %}
+{% if afi_config.advertise_all_vni is defined %}
+ advertise-all-vni
+{% endif %}
+{% if afi_config.advertise_default_gw is defined %}
+ advertise-default-gw
+{% endif %}
+{% if afi_config.advertise_pip is defined and afi_config.advertise_pip is not none %}
+ advertise-pip ip {{ afi_config.advertise_pip }}
+{% endif %}
+{% if afi_config.advertise_svi_ip is defined %}
+ advertise-svi-ip
+{% endif %}
+{% if afi_config.rt_auto_derive is defined %}
+ autort rfc8365-compatible
+{% endif %}
+{% if afi_config.flooding is defined and afi_config.flooding.disable is defined %}
+ flooding disable
+{% endif %}
+{% if afi_config.flooding is defined and afi_config.flooding.head_end_replication is defined %}
+ flooding head-end-replication
+{% endif %}
+{% if afi_config.rd is defined and afi_config.rd is not none %}
+ rd {{ afi_config.rd }}
+{% endif %}
+{% if afi_config.route_target is defined and afi_config.route_target is not none %}
+{% if afi_config.route_target.both is defined and afi_config.route_target.both is not none %}
+ route-target both {{ afi_config.route_target.both }}
+{% endif %}
+{% if afi_config.route_target.export is defined and afi_config.route_target.export is not none %}
+ route-target export {{ afi_config.route_target.export }}
+{% endif %}
+{% if afi_config.route_target.import is defined and afi_config.route_target.import is not none %}
+ route-target import {{ afi_config.route_target.import }}
+{% endif %}
+{% endif %}
+{% if afi_config.vni is defined and afi_config.vni is not none %}
+{% for vni, vni_config in afi_config.vni.items() %}
+ vni {{ vni }}
+{% if vni_config.advertise_default_gw is defined %}
+ advertise-default-gw
+{% endif %}
+{% if vni_config.advertise_svi_ip is defined %}
+ advertise-svi-ip
+{% endif %}
+{% if vni_config.rd is defined and vni_config.rd is not none %}
+ rd {{ vni_config.rd }}
+{% endif %}
+{% if vni_config.route_target is defined and vni_config.route_target is not none %}
+{% if vni_config.route_target.both is defined and vni_config.route_target.both is not none %}
+ route-target both {{ vni_config.route_target.both }}
+{% endif %}
+{% if vni_config.route_target.export is defined and vni_config.route_target.export is not none %}
+ route-target export {{ vni_config.route_target.export }}
+{% endif %}
+{% if vni_config.route_target.import is defined and vni_config.route_target.import is not none %}
+ route-target import {{ vni_config.route_target.import }}
+{% endif %}
+{% endif %}
+ exit-vni
+{% endfor %}
+{% endif %}
+ exit-address-family
+{% endfor %}
+{% endif %}
+ !
+{% if peer_group is defined and peer_group is not none %}
+{% for peer, config in peer_group.items() %}
+{{ bgp_neighbor(peer, config, true) }}
+{% endfor %}
+{% endif %}
+ !
+{% if neighbor is defined and neighbor is not none %}
+{% for peer, config in neighbor.items() %}
+{{ bgp_neighbor(peer, config) }}
+{% endfor %}
+{% endif %}
+ !
+{% if listen is defined %}
+{% if listen.limit is defined and listen.limit is not none %}
+ bgp listen limit {{ listen.limit }}
+{% endif %}
+{% for prefix, options in listen.range.items() %}
+{% if options.peer_group is defined and options.peer_group is not none %}
+ bgp listen range {{ prefix }} peer-group {{ options.peer_group }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% if parameters is defined %}
+{% if parameters.always_compare_med is defined %}
+ bgp always-compare-med
+{% endif %}
+{% if parameters.bestpath is defined and parameters.bestpath is not none %}
+{% if parameters.bestpath.compare_routerid is defined %}
+ bgp bestpath compare-routerid
+{% endif %}
+{% if parameters.bestpath.as_path is defined and parameters.bestpath.as_path is not none %}
+{% for option in parameters.bestpath.as_path %}
+ bgp bestpath as-path {{ option|replace('_', '-') }}
+{% endfor %}
+{% endif %}
+{% if parameters.bestpath.med is defined and parameters.bestpath.med is not none %}
+ bgp bestpath med {{ 'confed' if parameters.bestpath.med.confed is defined }} {{ 'missing-as-worst' if parameters.bestpath.med.missing_as_worst is defined }}
+{% endif %}
+{% endif %}
+{% if parameters.cluster_id is defined and parameters.cluster_id is not none %}
+ bgp cluster-id {{ parameters.cluster_id }}
+{% endif %}
+{% if parameters.confederation is defined and parameters.confederation is not none %}
+{% if parameters.confederation.identifier is defined and parameters.confederation.identifier is not none %}
+ bgp confederation identifier {{ parameters.confederation.identifier }}
+{% endif %}
+{% if parameters.confederation.peers is defined and parameters.confederation.peers is not none %}
+ bgp confederation peers {{ parameters.confederation.peers }}
+{% endif %}
+{% endif %}
+{% if parameters.dampening is defined and parameters.dampening is defined and parameters.dampening.half_life is defined and parameters.dampening.half_life is not none %}
+{# Doesn't work in current FRR configuration; vtysh (bgp dampening 16 751 2001 61) #}
+ bgp dampening {{ parameters.dampening.half_life }} {{ parameters.dampening.re_use if parameters.dampening.re_use is defined }} {{ parameters.dampening.start_suppress_time if parameters.dampening.start_suppress_time is defined }} {{ parameters.dampening.max_suppress_time if parameters.dampening.max_suppress_time is defined }}
+{% endif %}
+{% if parameters.default is defined and parameters.default is not none %}
+{% if parameters.default.local_pref is defined and parameters.default.local_pref is not none %}
+ bgp default local-preference {{ parameters.default.local_pref }}
+{% endif %}
+{% endif %}
+{% if parameters.deterministic_med is defined %}
+ bgp deterministic-med
+{% endif %}
+{% if parameters.distance is defined and parameters.distance is not none %}
+{% if parameters.distance.global is defined and parameters.distance.global.external is defined and parameters.distance.global.internal is defined and parameters.distance.global.local is defined %}
+ distance bgp {{ parameters.distance.global.external }} {{ parameters.distance.global.internal }} {{ parameters.distance.global.local }}
+{% endif %}
+{% if parameters.distance.prefix is defined and parameters.distance.prefix is not none %}
+{% for prefix in parameters.distance.prefix %}
+ distance {{ parameters.distance.prefix[prefix].distance }} {{ prefix }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{% if parameters.graceful_restart is defined %}
+ bgp graceful-restart {{ 'stalepath-time ' ~ parameters.graceful_restart.stalepath_time if parameters.graceful_restart.stalepath_time is defined }}
+{% endif %}
+{% if parameters.graceful_shutdown is defined %}
+ bgp graceful-shutdown
+{% endif %}
+{% if parameters.log_neighbor_changes is defined %}
+ bgp log-neighbor-changes
+{% endif %}
+{% if parameters.network_import_check is defined %}
+ bgp network import-check
+{% endif %}
+{% if parameters.no_client_to_client_reflection is defined %}
+ no bgp client-to-client reflection
+{% endif %}
+{% if parameters.no_fast_external_failover is defined %}
+ no bgp fast-external-failover
+{% endif %}
+{% if parameters.router_id is defined and parameters.router_id is not none %}
+ bgp router-id {{ parameters.router_id }}
+{% endif %}
+{% endif %}
+{% if timers is defined and timers.keepalive is defined and timers.holdtime is defined %}
+ timers bgp {{ timers.keepalive }} {{ timers.holdtime }}
+{% endif %}
+ end
+! \ No newline at end of file