{% 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 }}
+{% for local_asn, local_asn_config in config.local_as.items() %}
+{# There can be only one local-as value, this is checked in the Python code #}
+ neighbor {{ neighbor }} local-as {{ local_asn }} {{ 'no-prepend' if local_asn_config.no_prepend is defined }} {{ 'replace-as' if local_asn_config.replace_as 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 %}
{% 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 %}
{% 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 %}
{% 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 }} 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 %}
{% 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
{% if afi_config.rd is defined and afi_config.rd is not none %}
rd {{ afi_config.rd }}
{% endif %}
{% 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 %}
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 %}
{% if afi_config.export is defined and afi_config.export.vpn is defined %}
export vpn
{% endif %}
{% if afi_config.import is defined and afi_config.import is not none %}
{% if afi_config.import.vpn is defined %}
import vpn
{% endif %}
{% if afi_config.import.vrf is defined and afi_config.import.vrf is not none %}
{% for vrf in afi_config.import.vrf %}
import vrf {{ vrf }}
{% endfor %}
{% endif %}
{% endif %}
{% if afi_config.label is defined and afi_config.label.vpn is defined and afi_config.label.vpn.export is defined and afi_config.label.vpn.export is not none %}
{% if parameters.bestpath.compare_routerid is defined %}
bgp bestpath compare-routerid
{% 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 %}
{% 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 %}
{% 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 %}