From 4f884631d937b16258f352e085db79e4398c0971 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 10 Feb 2021 21:05:28 +0100 Subject: ripng: T3281: migrate to get_config_dict() and FRR reload --- data/templates/frr/ripng.frr.tmpl | 82 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 data/templates/frr/ripng.frr.tmpl (limited to 'data/templates/frr') diff --git a/data/templates/frr/ripng.frr.tmpl b/data/templates/frr/ripng.frr.tmpl new file mode 100644 index 000000000..ac14dfd3f --- /dev/null +++ b/data/templates/frr/ripng.frr.tmpl @@ -0,0 +1,82 @@ +! +router ripng +{% if default_information is defined and default_information.originate is defined %} + default-information originate +{% endif %} +{% if default_metric is defined and default_metric is not none %} + default-metric {{ default_metric }} +{% endif %} +{% if aggregate_address is defined and aggregate_address is not none %} +{% for prefix in aggregate_address %} + aggregate-address {{ prefix }} +{% endfor %} +{% endif %} +{% if passive_interface is defined and passive_interface is not none %} +{% for ifname in passive_interface %} + passive-interface {{ ifname }} +{% endfor %} +{% endif %} +{% if interface is defined and interface is not none %} +{% for ifname in interface %} + network {{ ifname }} +{% endfor %} +{% endif %} +{% if network is defined and network is not none %} +{% for net in network %} + network {{ net }} +{% endfor %} +{% endif %} +{% if route is defined and route is not none %} +{% for prefix in route %} + route {{ prefix }} +{% endfor %} +{% endif %} +{% if redistribute is defined and redistribute is not none %} +{% for protocol, protocol_config in redistribute.items() %} +{% if protocol == 'ospfv3' %} +{% set protocol = 'ospf6' %} +{% endif %} + redistribute {{ protocol }} {{ 'metric ' + protocol_config.metric if protocol_config.metric is defined }} {{ 'route-map ' + protocol_config.route_map if protocol_config.route_map is defined }} +{% endfor %} +{% endif %} +{# timers have default values #} + timers basic {{ timers['update'] }} {{ timers.timeout }} {{ timers.garbage_collection }} +{% if distribute_list is defined and distribute_list is not none %} +{% if distribute_list.access_list is defined and distribute_list.access_list is not none %} +{% if distribute_list.access_list.in is defined and distribute_list.access_list.in is not none %} + ipv6 distribute-list {{ distribute_list.access_list.in }} in +{% endif %} +{% if distribute_list.access_list.out is defined and distribute_list.access_list.out is not none %} + ipv6 distribute-list {{ distribute_list.access_list.out }} out +{% endif %} +{% endif %} +{% if distribute_list.interface is defined and distribute_list.interface is not none %} +{% for interface, interface_config in distribute_list.interface.items() %} +{% if interface_config.access_list is defined and interface_config.access_list is not none %} +{% if interface_config.access_list.in is defined and interface_config.access_list.in is not none %} + ipv6 distribute-list {{ interface_config.access_list.in }} in {{ interface }} +{% endif %} +{% if interface_config.access_list.out is defined and interface_config.access_list.out is not none %} + ipv6 distribute-list {{ interface_config.access_list.out }} out {{ interface }} +{% endif %} +{% endif %} +{% if interface_config.prefix_list is defined and interface_config.prefix_list is not none %} +{% if interface_config.prefix_list.in is defined and interface_config.prefix_list.in is not none %} + ipv6 distribute-list prefix {{ interface_config.prefix_list.in }} in {{ interface }} +{% endif %} +{% if interface_config.prefix_list.out is defined and interface_config.prefix_list.out is not none %} + ipv6 distribute-list prefix {{ interface_config.prefix_list.out }} out {{ interface }} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +{% if distribute_list.prefix_list is defined and distribute_list.prefix_list is not none %} +{% if distribute_list.prefix_list.in is defined and distribute_list.prefix_list.in is not none %} + ipv6 distribute-list prefix {{ distribute_list.prefix_list.in }} in +{% endif %} +{% if distribute_list.prefix_list.out is defined and distribute_list.prefix_list.out is not none %} + ipv6 distribute-list prefix {{ distribute_list.prefix_list.out }} out +{% endif %} +{% endif %} +{% endif %} +! -- cgit v1.2.3 From a72ea95cb276e13713e4a6433707e368ce8ee8fa Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 10 Feb 2021 21:05:52 +0100 Subject: rip: T2547: fix indention of distribute-list in FRR template --- data/templates/frr/rip.frr.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'data/templates/frr') diff --git a/data/templates/frr/rip.frr.tmpl b/data/templates/frr/rip.frr.tmpl index c0d062fc6..50db2e9de 100644 --- a/data/templates/frr/rip.frr.tmpl +++ b/data/templates/frr/rip.frr.tmpl @@ -114,10 +114,10 @@ router rip {% endif %} {% if distribute_list.prefix_list is defined and distribute_list.prefix_list is not none %} {% if distribute_list.prefix_list.in is defined and distribute_list.prefix_list.in is not none %} -distribute-list prefix {{ distribute_list.prefix_list.in }} in + distribute-list prefix {{ distribute_list.prefix_list.in }} in {% endif %} {% if distribute_list.prefix_list.out is defined and distribute_list.prefix_list.out is not none %} -distribute-list prefix {{ distribute_list.prefix_list.out }} out + distribute-list prefix {{ distribute_list.prefix_list.out }} out {% endif %} {% endif %} {% endif %} -- cgit v1.2.3 From 66282cc8a5c8ced4dee8414e5fcb5cbaa457781f Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 11 Feb 2021 20:00:14 +0100 Subject: ripng: T3281: move common parts into Jinja2 include --- data/templates/frr/rip.frr.tmpl | 34 +------------------------ data/templates/frr/rip_ripng.frr.j2 | 36 ++++++++++++++++++++++++++ data/templates/frr/ripng.frr.tmpl | 50 +++++++++++-------------------------- 3 files changed, 51 insertions(+), 69 deletions(-) create mode 100644 data/templates/frr/rip_ripng.frr.j2 (limited to 'data/templates/frr') diff --git a/data/templates/frr/rip.frr.tmpl b/data/templates/frr/rip.frr.tmpl index 50db2e9de..bc92bddf9 100644 --- a/data/templates/frr/rip.frr.tmpl +++ b/data/templates/frr/rip.frr.tmpl @@ -35,12 +35,6 @@ interface {{ iface }} {% endif %} ! router rip -{% if default_information is defined and default_information.originate is defined %} - default-information originate -{% endif %} -{% if default_metric is defined and default_metric is not none %} - default-metric {{ default_metric }} -{% endif %} {% if default_distance is defined and default_distance is not none %} distance {{ default_distance }} {% endif %} @@ -56,33 +50,6 @@ router rip neighbor {{ address }} {% endfor %} {% endif %} -{% if network is defined and network is not none %} -{% for prefix in network %} - network {{ prefix }} -{% endfor %} -{% endif %} -{% if interface is defined and interface is not none %} -{% for ifname in interface %} - network {{ ifname }} -{% endfor %} -{% endif %} -{% if passive_interface is defined and passive_interface is not none %} -{% for ifname in passive_interface %} - passive-interface {{ ifname }} -{% endfor %} -{% endif %} -{% if redistribute is defined and redistribute is not none %} -{% for protocol, protocol_config in redistribute.items() %} - redistribute {{ protocol }} {{ 'metric ' + protocol_config.metric if protocol_config.metric is defined }} {{ 'route-map ' + protocol_config.route_map if protocol_config.route_map is defined }} -{% endfor %} -{% endif %} -{% if route is defined and route is not none %} -{% for prefix in route %} - route {{ prefix }} -{% endfor %} -{% endif %} -{# timers have default values #} - timers basic {{ timers['update'] }} {{ timers.timeout }} {{ timers.garbage_collection }} {% if distribute_list is defined and distribute_list is not none %} {% if distribute_list.access_list is defined and distribute_list.access_list is not none %} {% if distribute_list.access_list.in is defined and distribute_list.access_list.in is not none %} @@ -121,4 +88,5 @@ router rip {% endif %} {% endif %} {% endif %} +{% include 'frr/rip_ripng.frr.j2' %} ! diff --git a/data/templates/frr/rip_ripng.frr.j2 b/data/templates/frr/rip_ripng.frr.j2 new file mode 100644 index 000000000..de180ee6b --- /dev/null +++ b/data/templates/frr/rip_ripng.frr.j2 @@ -0,0 +1,36 @@ +{% if default_information is defined and default_information.originate is defined %} + default-information originate +{% endif %} +{% if default_metric is defined and default_metric is not none %} + default-metric {{ default_metric }} +{% endif %} +{% if passive_interface is defined and passive_interface is not none %} +{% for interface in passive_interface %} + passive-interface {{ interface }} +{% endfor %} +{% endif %} +{% if network is defined and network is not none %} +{% for prefix in network %} + network {{ prefix }} +{% endfor %} +{% endif %} +{% if interface is defined and interface is not none %} +{% for ifname in interface %} + network {{ ifname }} +{% endfor %} +{% endif %} +{% if route is defined and route is not none %} +{% for prefix in route %} + route {{ prefix }} +{% endfor %} +{% endif %} +{# timers have default values #} + timers basic {{ timers['update'] }} {{ timers.timeout }} {{ timers.garbage_collection }} +{% if redistribute is defined and redistribute is not none %} +{% for protocol, protocol_config in redistribute.items() %} +{% if protocol == 'ospfv3' %} +{% set protocol = 'ospf6' %} +{% endif %} + redistribute {{ protocol }} {{ 'metric ' + protocol_config.metric if protocol_config.metric is defined }} {{ 'route-map ' + protocol_config.route_map if protocol_config.route_map is defined }} +{% endfor %} +{% endif %} diff --git a/data/templates/frr/ripng.frr.tmpl b/data/templates/frr/ripng.frr.tmpl index ac14dfd3f..25df15121 100644 --- a/data/templates/frr/ripng.frr.tmpl +++ b/data/templates/frr/ripng.frr.tmpl @@ -1,46 +1,23 @@ ! -router ripng -{% if default_information is defined and default_information.originate is defined %} - default-information originate -{% endif %} -{% if default_metric is defined and default_metric is not none %} - default-metric {{ default_metric }} +{# Interface specific configuration #} +{% if interface is defined and interface is not none %} +{% for iface, iface_config in interface.items() %} +interface {{ iface }} +{% if iface_config.split_horizon is defined and iface_config.split_horizon.disable is defined %} + no ipv6 rip split-horizon +{% endif %} +{% if iface_config.split_horizon is defined and iface_config.split_horizon.poison_reverse is defined %} + ipv6 rip split-horizon poisoned-reverse +{% endif %} +{% endfor %} {% endif %} +! +router ripng {% if aggregate_address is defined and aggregate_address is not none %} {% for prefix in aggregate_address %} aggregate-address {{ prefix }} {% endfor %} {% endif %} -{% if passive_interface is defined and passive_interface is not none %} -{% for ifname in passive_interface %} - passive-interface {{ ifname }} -{% endfor %} -{% endif %} -{% if interface is defined and interface is not none %} -{% for ifname in interface %} - network {{ ifname }} -{% endfor %} -{% endif %} -{% if network is defined and network is not none %} -{% for net in network %} - network {{ net }} -{% endfor %} -{% endif %} -{% if route is defined and route is not none %} -{% for prefix in route %} - route {{ prefix }} -{% endfor %} -{% endif %} -{% if redistribute is defined and redistribute is not none %} -{% for protocol, protocol_config in redistribute.items() %} -{% if protocol == 'ospfv3' %} -{% set protocol = 'ospf6' %} -{% endif %} - redistribute {{ protocol }} {{ 'metric ' + protocol_config.metric if protocol_config.metric is defined }} {{ 'route-map ' + protocol_config.route_map if protocol_config.route_map is defined }} -{% endfor %} -{% endif %} -{# timers have default values #} - timers basic {{ timers['update'] }} {{ timers.timeout }} {{ timers.garbage_collection }} {% if distribute_list is defined and distribute_list is not none %} {% if distribute_list.access_list is defined and distribute_list.access_list is not none %} {% if distribute_list.access_list.in is defined and distribute_list.access_list.in is not none %} @@ -79,4 +56,5 @@ router ripng {% endif %} {% endif %} {% endif %} +{% include 'frr/rip_ripng.frr.j2' %} ! -- cgit v1.2.3 From f4e8062651a8feece2d8538755db139d5e0790f7 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 13 Feb 2021 20:42:13 +0100 Subject: bgp: T1513: extend supported evpn support/cli options Add CLI options for: - advertise-pip - rt-auto-derive - flooding - rd - route-target --- data/templates/frr/bgp.frr.tmpl | 144 +++++++++++++++++------------ interface-definitions/protocols-bgp.xml.in | 92 ++++++++++++++++++ 2 files changed, 177 insertions(+), 59 deletions(-) (limited to 'data/templates/frr') diff --git a/data/templates/frr/bgp.frr.tmpl b/data/templates/frr/bgp.frr.tmpl index 74874ee43..9dafc7f91 100644 --- a/data/templates/frr/bgp.frr.tmpl +++ b/data/templates/frr/bgp.frr.tmpl @@ -78,74 +78,74 @@ {% elif af == 'l2vpn_evpn' %} address-family l2vpn evpn {% endif %} -{% if config.address_family[af].allowas_in is defined and config.address_family[af].allowas_in is not none %} - neighbor {{ neighbor }} allowas-in {{ config.address_family[af].allowas_in.number if config.address_family[af].allowas_in.number is defined }} +{% if config.afi_config.allowas_in is defined and config.afi_config.allowas_in is not none %} + neighbor {{ neighbor }} allowas-in {{ config.afi_config.allowas_in.number if config.afi_config.allowas_in.number is defined }} {% endif %} -{% if config.address_family[af].remove_private_as is defined %} +{% if config.afi_config.remove_private_as is defined %} neighbor {{ neighbor }} remove-private-AS {% endif %} -{% if config.address_family[af].route_reflector_client is defined %} +{% if config.afi_config.route_reflector_client is defined %} neighbor {{ neighbor }} route-reflector-client {% endif %} -{% if config.address_family[af].weight is defined and config.address_family[af].weight is not none %} - neighbor {{ neighbor }} weight {{ config.address_family[af].weight }} +{% if config.afi_config.weight is defined and config.afi_config.weight is not none %} + neighbor {{ neighbor }} weight {{ config.afi_config.weight }} {% endif %} -{% if config.address_family[af].attribute_unchanged is defined and config.address_family[af].attribute_unchanged is not none %} - neighbor {{ neighbor }} attribute-unchanged {{ 'as-path ' if config.address_family[af].attribute_unchanged.as_path is defined }}{{ 'med ' if config.address_family[af].attribute_unchanged.med is defined }}{{ 'next-hop ' if config.address_family[af].attribute_unchanged.next_hop is defined }} +{% if config.afi_config.attribute_unchanged is defined and config.afi_config.attribute_unchanged is not none %} + neighbor {{ neighbor }} attribute-unchanged {{ 'as-path ' if config.afi_config.attribute_unchanged.as_path is defined }}{{ 'med ' if config.afi_config.attribute_unchanged.med is defined }}{{ 'next-hop ' if config.afi_config.attribute_unchanged.next_hop is defined }} {% endif %} -{% if config.address_family[af].capability is defined and config.address_family[af].capability.orf is defined and config.address_family[af].capability.orf.prefix_list is defined and config.address_family[af].capability.orf.prefix_list is not none %} - neighbor {{ neighbor }} capability orf prefix-list {{ config.address_family[af].capability.orf.prefix_list }} +{% if config.afi_config.capability is defined and config.afi_config.capability.orf is defined and config.afi_config.capability.orf.prefix_list is defined and config.afi_config.capability.orf.prefix_list is not none %} + neighbor {{ neighbor }} capability orf prefix-list {{ config.afi_config.capability.orf.prefix_list }} {% endif %} -{% if config.address_family[af].default_originate is defined %} - neighbor {{ neighbor }} default-originate {{ 'route-map ' + config.address_family[af].default_originate.route_map if config.address_family[af].default_originate.route_map is defined }} +{% if config.afi_config.default_originate is defined %} + neighbor {{ neighbor }} default-originate {{ 'route-map ' + config.afi_config.default_originate.route_map if config.afi_config.default_originate.route_map is defined }} {% endif %} -{% if config.address_family[af].distribute_list is defined and config.address_family[af].distribute_list is not none %} -{% if config.address_family[af].distribute_list.export is defined and config.address_family[af].distribute_list.export is not none %} - neighbor {{ neighbor }} distribute-list {{ config.address_family[af].distribute_list.export }} out +{% if config.afi_config.distribute_list is defined and config.afi_config.distribute_list is not none %} +{% if config.afi_config.distribute_list.export is defined and config.afi_config.distribute_list.export is not none %} + neighbor {{ neighbor }} distribute-list {{ config.afi_config.distribute_list.export }} out {% endif %} -{% if config.address_family[af].distribute_list.import is defined and config.address_family[af].distribute_list.import is not none %} - neighbor {{ neighbor }} distribute-list {{ config.address_family[af].distribute_list.import }} in +{% if config.afi_config.distribute_list.import is defined and config.afi_config.distribute_list.import is not none %} + neighbor {{ neighbor }} distribute-list {{ config.afi_config.distribute_list.import }} in {% endif %} {% endif %} -{% if config.address_family[af].filter_list is defined and config.address_family[af].filter_list is not none %} -{% if config.address_family[af].filter_list.export is defined and config.address_family[af].filter_list.export is not none %} - neighbor {{ neighbor }} filter-list {{ config.address_family[af].filter_list.export }} out +{% if config.afi_config.filter_list is defined and config.afi_config.filter_list is not none %} +{% if config.afi_config.filter_list.export is defined and config.afi_config.filter_list.export is not none %} + neighbor {{ neighbor }} filter-list {{ config.afi_config.filter_list.export }} out {% endif %} -{% if config.address_family[af].filter_list.import is defined and config.address_family[af].filter_list.import is not none %} - neighbor {{ neighbor }} filter-list {{ config.address_family[af].filter_list.import }} in +{% if config.afi_config.filter_list.import is defined and config.afi_config.filter_list.import is not none %} + neighbor {{ neighbor }} filter-list {{ config.afi_config.filter_list.import }} in {% endif %} {% endif %} -{% if config.address_family[af].maximum_prefix is defined and config.address_family[af].maximum_prefix is not none %} - neighbor {{ neighbor }} maximum-prefix {{ config.address_family[af].maximum_prefix }} +{% if config.afi_config.maximum_prefix is defined and config.afi_config.maximum_prefix is not none %} + neighbor {{ neighbor }} maximum-prefix {{ config.afi_config.maximum_prefix }} {% endif %} -{% if config.address_family[af].nexthop_self is defined %} +{% if config.afi_config.nexthop_self is defined %} {# https://phabricator.vyos.net/T1817 #} - neighbor {{ neighbor }} next-hop-self {{ 'force' if config.address_family[af].nexthop_self.force is defined }} + neighbor {{ neighbor }} next-hop-self {{ 'force' if config.afi_config.nexthop_self.force is defined }} {% endif %} -{% if config.address_family[af].route_server_client is defined %} +{% if config.afi_config.route_server_client is defined %} neighbor {{ neighbor }} route-server-client {% endif %} -{% if config.address_family[af].route_map is defined and config.address_family[af].route_map is not none %} -{% if config.address_family[af].route_map.export is defined and config.address_family[af].route_map.export is not none %} - neighbor {{ neighbor }} route-map {{ config.address_family[af].route_map.export }} out +{% if config.afi_config.route_map is defined and config.afi_config.route_map is not none %} +{% if config.afi_config.route_map.export is defined and config.afi_config.route_map.export is not none %} + neighbor {{ neighbor }} route-map {{ config.afi_config.route_map.export }} out {% endif %} -{% if config.address_family[af].route_map.import is defined and config.address_family[af].route_map.import is not none %} - neighbor {{ neighbor }} route-map {{ config.address_family[af].route_map.import }} in +{% if config.afi_config.route_map.import is defined and config.afi_config.route_map.import is not none %} + neighbor {{ neighbor }} route-map {{ config.afi_config.route_map.import }} in {% endif %} {% endif %} -{% if config.address_family[af].prefix_list is defined and config.address_family[af].prefix_list is not none %} -{% if config.address_family[af].prefix_list.export is defined and config.address_family[af].prefix_list.export is not none %} - neighbor {{ neighbor }} prefix-list {{ config.address_family[af].prefix_list.export }} out +{% if config.afi_config.prefix_list is defined and config.afi_config.prefix_list is not none %} +{% if config.afi_config.prefix_list.export is defined and config.afi_config.prefix_list.export is not none %} + neighbor {{ neighbor }} prefix-list {{ config.afi_config.prefix_list.export }} out {% endif %} -{% if config.address_family[af].prefix_list.import is defined and config.address_family[af].prefix_list.import is not none %} - neighbor {{ neighbor }} prefix-list {{ config.address_family[af].prefix_list.import }} in +{% if config.afi_config.prefix_list.import is defined and config.afi_config.prefix_list.import is not none %} + neighbor {{ neighbor }} prefix-list {{ config.afi_config.prefix_list.import }} in {% endif %} {% endif %} -{% if config.address_family[af].soft_reconfiguration is defined and config.address_family[af].soft_reconfiguration.inbound is defined %} +{% if config.afi_config.soft_reconfiguration is defined and config.afi_config.soft_reconfiguration.inbound is defined %} neighbor {{ neighbor }} soft-reconfiguration inbound {% endif %} -{% if config.address_family[af].unsuppress_map is defined and config.address_family[af].unsuppress_map is not none %} - neighbor {{ neighbor }} unsuppress-map {{ config.address_family[af].unsuppress_map }} +{% if config.afi_config.unsuppress_map is defined and config.afi_config.unsuppress_map is not none %} + neighbor {{ neighbor }} unsuppress-map {{ config.afi_config.unsuppress_map }} {% endif %} neighbor {{ neighbor }} activate exit-address-family @@ -159,53 +159,79 @@ router bgp {{ asn }} {# https://phabricator.vyos.net/T3183 & https://phabricator.vyos.net/T2100 #} no bgp ebgp-requires-policy {% if address_family is defined and address_family is not none %} -{% for af in address_family %} +{% for afi, afi_config in address_family.items() %} ! -{% if af == 'ipv4_unicast' %} +{% if afi == 'ipv4_unicast' %} address-family ipv4 unicast -{% elif af == 'ipv6_unicast' %} +{% elif afi == 'ipv6_unicast' %} address-family ipv6 unicast -{% elif af == 'l2vpn_evpn' %} +{% elif afi == 'l2vpn_evpn' %} address-family l2vpn evpn {% endif %} -{% if address_family[af].aggregate_address is defined and address_family[af].aggregate_address is not none %} -{% for ip in address_family[af].aggregate_address %} - aggregate-address {{ ip }}{{ ' as-set' if address_family[af].aggregate_address[ip].as_set is defined }}{{ ' summary-only' if address_family[af].aggregate_address[ip].summary_only is defined }} +{% 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 address_family[af].redistribute is defined and address_family[af].redistribute is not none %} -{% for protocol in address_family[af].redistribute %} +{% if afi_config.redistribute is defined and afi_config.redistribute is not none %} +{% for protocol in afi_config.redistribute %} {% if protocol == 'table' %} - redistribute table {{ address_family[af].redistribute[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 address_family[af].redistribute[protocol].metric is defined %} metric {{ address_family[af].redistribute[protocol].metric }}{% endif %}{% if address_family[af].redistribute[protocol].route_map is defined %} route-map {{ address_family[af].redistribute[protocol].route_map }}{% 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 address_family[af].network is defined and address_family[af].network is not none %} -{% for network in address_family[af].network %} - network {{ network }}{% if address_family[af].network[network].route_map is defined %} route-map {{ address_family[af].network[network].route_map }}{% endif %}{% if address_family[af].network[network].backdoor is defined %} backdoor{% 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 %} {####### we need this blank line!! #######} {% endfor %} {% endif %} -{% if address_family[af].advertise_all_vni is defined %} +{% if afi_config.advertise_all_vni is defined %} advertise-all-vni {% endif %} -{% if address_family[af].advertise_default_gw is defined %} +{% if afi_config.advertise_default_gw is defined %} advertise-default-gw {% endif %} -{% if address_family[af].advertise_svi_ip is defined %} +{% 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 address_family[af].vni is defined and address_family[af].vni is not none %} - vni {{ address_family[af].vni }} +{% 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 %} + vni {{ afi_config.vni }} exit-vni {% endif %} exit-address-family diff --git a/interface-definitions/protocols-bgp.xml.in b/interface-definitions/protocols-bgp.xml.in index 3b7910766..ecb5b94d6 100644 --- a/interface-definitions/protocols-bgp.xml.in +++ b/interface-definitions/protocols-bgp.xml.in @@ -234,12 +234,104 @@ + + + EVPN system primary IP + + ipv4 + IP address + + + + + + Advertise svi mac-ip routes in EVPN + + + Auto derivation of Route Target (RFC8365) + + + + + + Specify handling for BUM packets + + + + + Do not flood any BUM packets + + + + + + Flood BUM packets using head-end replication + + + + + + + + Route Distinguisher + + txt + Route Distinguisher, asn:xxx + + + ^[0-9]{1,10}:[0-9]{1,5}$ + + + + + + Route Target + + + + + Route Target both import and export + + txt + Route target (x.x.x.x:yyy|xxxx:yyyy) + + + ^((25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)(\.(25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)){3}|[0-9]{1,10}):[0-9]{1,5}$ + + + + + + Route Target export + + txt + Route target (x.x.x.x:yyy|xxxx:yyyy) + + + ^((25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)(\.(25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)){3}|[0-9]{1,10}):[0-9]{1,5}$ + + + + + + Route Target import + + txt + Route target (x.x.x.x:yyy|xxxx:yyyy) + + + ^((25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)(\.(25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)){3}|[0-9]{1,10}):[0-9]{1,5}$ + + + + + VXLAN Network Identifier -- cgit v1.2.3 From 3da513e58da35b00722ac40530616ad6c01f731e Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 13 Feb 2021 21:18:10 +0100 Subject: bgp: T2387: bgp_neighbor macro should access address family dict with items() --- data/templates/frr/bgp.frr.tmpl | 89 ++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 45 deletions(-) (limited to 'data/templates/frr') diff --git a/data/templates/frr/bgp.frr.tmpl b/data/templates/frr/bgp.frr.tmpl index 9dafc7f91..bfaac7144 100644 --- a/data/templates/frr/bgp.frr.tmpl +++ b/data/templates/frr/bgp.frr.tmpl @@ -70,82 +70,81 @@ {% endif %} ! {% if config.address_family is defined and config.address_family is not none %} -{% for af in config.address_family %} -{% if af == 'ipv4_unicast' %} +{% for afi, afi_config in config.address_family.items() %} +{% if afi == 'ipv4_unicast' %} address-family ipv4 unicast -{% elif af == 'ipv6_unicast' %} +{% elif afi == 'ipv6_unicast' %} address-family ipv6 unicast -{% elif af == 'l2vpn_evpn' %} +{% elif afi == 'l2vpn_evpn' %} address-family l2vpn evpn {% endif %} -{% if config.afi_config.allowas_in is defined and config.afi_config.allowas_in is not none %} - neighbor {{ neighbor }} allowas-in {{ config.afi_config.allowas_in.number if config.afi_config.allowas_in.number is defined }} +{% 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 config.afi_config.remove_private_as is defined %} +{% if afi_config.remove_private_as is defined %} neighbor {{ neighbor }} remove-private-AS {% endif %} -{% if config.afi_config.route_reflector_client is defined %} +{% if afi_config.route_reflector_client is defined %} neighbor {{ neighbor }} route-reflector-client {% endif %} -{% if config.afi_config.weight is defined and config.afi_config.weight is not none %} - neighbor {{ neighbor }} weight {{ config.afi_config.weight }} +{% if afi_config.weight is defined and afi_config.weight is not none %} + neighbor {{ neighbor }} weight {{ afi_config.weight }} {% endif %} -{% if config.afi_config.attribute_unchanged is defined and config.afi_config.attribute_unchanged is not none %} - neighbor {{ neighbor }} attribute-unchanged {{ 'as-path ' if config.afi_config.attribute_unchanged.as_path is defined }}{{ 'med ' if config.afi_config.attribute_unchanged.med is defined }}{{ 'next-hop ' if config.afi_config.attribute_unchanged.next_hop is defined }} +{% 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 config.afi_config.capability is defined and config.afi_config.capability.orf is defined and config.afi_config.capability.orf.prefix_list is defined and config.afi_config.capability.orf.prefix_list is not none %} - neighbor {{ neighbor }} capability orf prefix-list {{ config.afi_config.capability.orf.prefix_list }} +{% 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 is not none %} + neighbor {{ neighbor }} capability orf prefix-list {{ afi_config.capability.orf.prefix_list }} {% endif %} -{% if config.afi_config.default_originate is defined %} - neighbor {{ neighbor }} default-originate {{ 'route-map ' + config.afi_config.default_originate.route_map if config.afi_config.default_originate.route_map is defined }} +{% 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 config.afi_config.distribute_list is defined and config.afi_config.distribute_list is not none %} -{% if config.afi_config.distribute_list.export is defined and config.afi_config.distribute_list.export is not none %} - neighbor {{ neighbor }} distribute-list {{ config.afi_config.distribute_list.export }} out +{% 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 config.afi_config.distribute_list.import is defined and config.afi_config.distribute_list.import is not none %} - neighbor {{ neighbor }} distribute-list {{ config.afi_config.distribute_list.import }} in +{% 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 config.afi_config.filter_list is defined and config.afi_config.filter_list is not none %} -{% if config.afi_config.filter_list.export is defined and config.afi_config.filter_list.export is not none %} - neighbor {{ neighbor }} filter-list {{ config.afi_config.filter_list.export }} out +{% 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 config.afi_config.filter_list.import is defined and config.afi_config.filter_list.import is not none %} - neighbor {{ neighbor }} filter-list {{ config.afi_config.filter_list.import }} in +{% 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 config.afi_config.maximum_prefix is defined and config.afi_config.maximum_prefix is not none %} - neighbor {{ neighbor }} maximum-prefix {{ config.afi_config.maximum_prefix }} +{% 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 config.afi_config.nexthop_self is defined %} -{# https://phabricator.vyos.net/T1817 #} - neighbor {{ neighbor }} next-hop-self {{ 'force' if config.afi_config.nexthop_self.force is defined }} +{% if afi_config.nexthop_self is defined %} + neighbor {{ neighbor }} next-hop-self {{ 'force' if afi_config.nexthop_self.force is defined }} {% endif %} -{% if config.afi_config.route_server_client is defined %} +{% if afi_config.route_server_client is defined %} neighbor {{ neighbor }} route-server-client {% endif %} -{% if config.afi_config.route_map is defined and config.afi_config.route_map is not none %} -{% if config.afi_config.route_map.export is defined and config.afi_config.route_map.export is not none %} - neighbor {{ neighbor }} route-map {{ config.afi_config.route_map.export }} out +{% 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 config.afi_config.route_map.import is defined and config.afi_config.route_map.import is not none %} - neighbor {{ neighbor }} route-map {{ config.afi_config.route_map.import }} in +{% 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 config.afi_config.prefix_list is defined and config.afi_config.prefix_list is not none %} -{% if config.afi_config.prefix_list.export is defined and config.afi_config.prefix_list.export is not none %} - neighbor {{ neighbor }} prefix-list {{ config.afi_config.prefix_list.export }} out +{% 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 config.afi_config.prefix_list.import is defined and config.afi_config.prefix_list.import is not none %} - neighbor {{ neighbor }} prefix-list {{ config.afi_config.prefix_list.import }} in +{% 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 config.afi_config.soft_reconfiguration is defined and config.afi_config.soft_reconfiguration.inbound is defined %} +{% if afi_config.soft_reconfiguration is defined and afi_config.soft_reconfiguration.inbound is defined %} neighbor {{ neighbor }} soft-reconfiguration inbound {% endif %} -{% if config.afi_config.unsuppress_map is defined and config.afi_config.unsuppress_map is not none %} - neighbor {{ neighbor }} unsuppress-map {{ config.afi_config.unsuppress_map }} +{% if afi_config.unsuppress_map is defined and afi_config.unsuppress_map is not none %} + neighbor {{ neighbor }} unsuppress-map {{ afi_config.unsuppress_map }} {% endif %} neighbor {{ neighbor }} activate exit-address-family -- cgit v1.2.3 From 0c814f19cdc81360005055dbf24b627ba6449877 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 14 Feb 2021 10:05:37 +0100 Subject: bgp: T1513: make vni a multi node --- data/templates/frr/bgp.frr.tmpl | 4 +++- interface-definitions/protocols-bgp.xml.in | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'data/templates/frr') diff --git a/data/templates/frr/bgp.frr.tmpl b/data/templates/frr/bgp.frr.tmpl index bfaac7144..792146be0 100644 --- a/data/templates/frr/bgp.frr.tmpl +++ b/data/templates/frr/bgp.frr.tmpl @@ -230,8 +230,10 @@ router bgp {{ asn }} {% endif %} {% endif %} {% if afi_config.vni is defined and afi_config.vni is not none %} - vni {{ afi_config.vni }} +{% for vni in afi_config.vni %} + vni {{ vni }} exit-vni +{% endfor %} {% endif %} exit-address-family {% endfor %} diff --git a/interface-definitions/protocols-bgp.xml.in b/interface-definitions/protocols-bgp.xml.in index ecb5b94d6..13caa7b63 100644 --- a/interface-definitions/protocols-bgp.xml.in +++ b/interface-definitions/protocols-bgp.xml.in @@ -342,6 +342,7 @@ + -- cgit v1.2.3 From d468102e66ff7ed784d794e6884983669bba108e Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 14 Feb 2021 10:09:50 +0100 Subject: bgp: T3308: add graceful-shutdown option --- data/templates/frr/bgp.frr.tmpl | 3 +++ interface-definitions/protocols-bgp.xml.in | 6 ++++++ smoketest/scripts/cli/test_protocols_bgp.py | 5 +++++ 3 files changed, 14 insertions(+) (limited to 'data/templates/frr') diff --git a/data/templates/frr/bgp.frr.tmpl b/data/templates/frr/bgp.frr.tmpl index 792146be0..8db6015d0 100644 --- a/data/templates/frr/bgp.frr.tmpl +++ b/data/templates/frr/bgp.frr.tmpl @@ -340,6 +340,9 @@ router bgp {{ asn }} {% 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 %} diff --git a/interface-definitions/protocols-bgp.xml.in b/interface-definitions/protocols-bgp.xml.in index 13caa7b63..d7bc86aff 100644 --- a/interface-definitions/protocols-bgp.xml.in +++ b/interface-definitions/protocols-bgp.xml.in @@ -852,6 +852,12 @@ + + + Graceful shutdown + + + Log neighbor up/down changes and reset reason diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py index 30d98976d..8bbf0a5d1 100755 --- a/smoketest/scripts/cli/test_protocols_bgp.py +++ b/smoketest/scripts/cli/test_protocols_bgp.py @@ -166,6 +166,7 @@ class TestProtocolsBGP(unittest.TestCase): def test_bgp_01_simple(self): router_id = '127.0.0.1' local_pref = '500' + stalepath_time = '60' self.session.set(base_path + ['parameters', 'router-id', router_id]) self.session.set(base_path + ['parameters', 'log-neighbor-changes']) @@ -173,6 +174,8 @@ class TestProtocolsBGP(unittest.TestCase): self.session.set(base_path + ['parameters', 'default', 'local-pref', local_pref]) # Deactivate IPv4 unicast for a peer by default self.session.set(base_path + ['parameters', 'default', 'no-ipv4-unicast']) + self.session.set(base_path + ['parameters', 'graceful-restart', 'stalepath-time', stalepath_time]) + self.session.set(base_path + ['parameters', 'graceful-shutdown']) # commit changes self.session.commit() @@ -184,6 +187,8 @@ class TestProtocolsBGP(unittest.TestCase): self.assertIn(f' bgp log-neighbor-changes', frrconfig) self.assertIn(f' bgp default local-preference {local_pref}', frrconfig) self.assertIn(f' no bgp default ipv4-unicast', frrconfig) + self.assertIn(f' bgp graceful-restart stalepath-time {stalepath_time}', frrconfig) + self.assertIn(f' bgp graceful-shutdown', frrconfig) def test_bgp_02_neighbors(self): -- cgit v1.2.3 From 081b747e2940ac042e39bac1f209d7df94a413bf Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 14 Feb 2021 11:26:48 +0100 Subject: bgp: T2387: bugfix missing options not added to FRR The following options were not represented in the Jinja2 template: - port - advertisement-interval - strict-capability-match In addition the smoketests have been extended to support IPv6 neighbors, too. --- data/templates/frr/bgp.frr.tmpl | 9 ++ smoketest/scripts/cli/test_protocols_bgp.py | 156 +++++++++++++++++++--------- 2 files changed, 118 insertions(+), 47 deletions(-) (limited to 'data/templates/frr') diff --git a/data/templates/frr/bgp.frr.tmpl b/data/templates/frr/bgp.frr.tmpl index 8db6015d0..62c675291 100644 --- a/data/templates/frr/bgp.frr.tmpl +++ b/data/templates/frr/bgp.frr.tmpl @@ -9,6 +9,9 @@ {% if config.remote_as is defined and config.remote_as is not none %} neighbor {{ neighbor }} remote-as {{ config.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 %} @@ -43,9 +46,15 @@ {% 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 %} diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py index 8bbf0a5d1..4c4abc600 100755 --- a/smoketest/scripts/cli/test_protocols_bgp.py +++ b/smoketest/scripts/cli/test_protocols_bgp.py @@ -19,6 +19,7 @@ import unittest from vyos.configsession import ConfigSession from vyos.configsession import ConfigSessionError +from vyos.template import is_ipv6 from vyos.util import cmd from vyos.util import process_named_running @@ -30,6 +31,8 @@ route_map_in = 'foo-map-in' route_map_out = 'foo-map-out' prefix_list_in = 'pfx-foo-in' prefix_list_out = 'pfx-foo-out' +prefix_list_in6 = 'pfx-foo-in6' +prefix_list_out6 = 'pfx-foo-out6' neighbor_config = { '192.0.2.1' : { @@ -62,6 +65,29 @@ neighbor_config = { 'multi_hop' : '5', 'update_src' : 'lo', }, + '2001:db8::1' : { + 'cap_dynamic' : '', + 'cap_ext_next' : '', + 'remote_as' : '123', + 'adv_interv' : '400', + 'passive' : '', + 'password' : 'VyOS-Secure123', + 'shutdown' : '', + 'cap_over' : '', + 'ttl_security' : '5', + 'local_as' : '300', + 'route_map_in' : route_map_in, + 'route_map_out': route_map_out, + }, + '2001:db8::2' : { + 'remote_as' : '456', + 'shutdown' : '', + 'no_cap_nego' : '', + 'port' : '667', + 'cap_strict' : '', + 'pfx_list_in' : prefix_list_in6, + 'pfx_list_out' : prefix_list_out6, + }, } peer_group_config = { @@ -112,11 +138,18 @@ class TestProtocolsBGP(unittest.TestCase): self.session.set(['policy', 'prefix-list', prefix_list_out, 'rule', '10', 'action', 'permit']) self.session.set(['policy', 'prefix-list', prefix_list_out, 'rule', '10', 'prefix', '192.0.2.128/25']) + self.session.set(['policy', 'prefix-list6', prefix_list_in6, 'rule', '10', 'action', 'permit']) + self.session.set(['policy', 'prefix-list6', prefix_list_in6, 'rule', '10', 'prefix', '2001:db8:1000::/64']) + self.session.set(['policy', 'prefix-list6', prefix_list_out6, 'rule', '10', 'action', 'deny']) + self.session.set(['policy', 'prefix-list6', prefix_list_out6, 'rule', '10', 'prefix', '2001:db8:2000::/64']) + def tearDown(self): self.session.delete(['policy', 'route-map', route_map_in]) self.session.delete(['policy', 'route-map', route_map_out]) self.session.delete(['policy', 'prefix-list', prefix_list_in]) self.session.delete(['policy', 'prefix-list', prefix_list_out]) + self.session.delete(['policy', 'prefix-list6', prefix_list_in6]) + self.session.delete(['policy', 'prefix-list6', prefix_list_out6]) self.session.delete(base_path) self.session.commit() @@ -194,47 +227,51 @@ class TestProtocolsBGP(unittest.TestCase): def test_bgp_02_neighbors(self): # Test out individual neighbor configuration items, not all of them are # also available to a peer-group! - for neighbor, config in neighbor_config.items(): - if 'adv_interv' in config: - self.session.set(base_path + ['neighbor', neighbor, 'advertisement-interval', config["adv_interv"]]) - if 'cap_dynamic' in config: - self.session.set(base_path + ['neighbor', neighbor, 'capability', 'dynamic']) - if 'cap_ext_next' in config: - self.session.set(base_path + ['neighbor', neighbor, 'capability', 'extended-nexthop']) - if 'description' in config: - self.session.set(base_path + ['neighbor', neighbor, 'description', config["description"]]) - if 'no_cap_nego' in config: - self.session.set(base_path + ['neighbor', neighbor, 'disable-capability-negotiation']) - if 'multi_hop' in config: - self.session.set(base_path + ['neighbor', neighbor, 'ebgp-multihop', config["multi_hop"]]) - if 'local_as' in config: - self.session.set(base_path + ['neighbor', neighbor, 'local-as', config["local_as"]]) - if 'cap_over' in config: - self.session.set(base_path + ['neighbor', neighbor, 'override-capability']) - if 'passive' in config: - self.session.set(base_path + ['neighbor', neighbor, 'passive']) - if 'password' in config: - self.session.set(base_path + ['neighbor', neighbor, 'password', config["password"]]) - if 'port' in config: - self.session.set(base_path + ['neighbor', neighbor, 'port', config["port"]]) - if 'remote_as' in config: - self.session.set(base_path + ['neighbor', neighbor, 'remote-as', config["remote_as"]]) - if 'cap_strict' in config: - self.session.set(base_path + ['neighbor', neighbor, 'strict-capability-match']) - if 'shutdown' in config: - self.session.set(base_path + ['neighbor', neighbor, 'shutdown']) - if 'ttl_security' in config: - self.session.set(base_path + ['neighbor', neighbor, 'ttl-security', 'hops', config["ttl_security"]]) - if 'update_src' in config: - self.session.set(base_path + ['neighbor', neighbor, 'update-source', config["update_src"]]) - if 'route_map_in' in config: - self.session.set(base_path + ['neighbor', neighbor, 'address-family', 'ipv4-unicast', 'route-map', 'import', config["route_map_in"]]) - if 'route_map_out' in config: - self.session.set(base_path + ['neighbor', neighbor, 'address-family', 'ipv4-unicast', 'route-map', 'export', config["route_map_out"]]) - if 'pfx_list_in' in config: - self.session.set(base_path + ['neighbor', neighbor, 'address-family', 'ipv4-unicast', 'prefix-list', 'import', config["pfx_list_in"]]) - if 'pfx_list_out' in config: - self.session.set(base_path + ['neighbor', neighbor, 'address-family', 'ipv4-unicast', 'prefix-list', 'export', config["pfx_list_out"]]) + for peer, peer_config in neighbor_config.items(): + afi = 'ipv4-unicast' + if is_ipv6(peer): + afi = 'ipv6-unicast' + + if 'adv_interv' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'advertisement-interval', peer_config["adv_interv"]]) + if 'cap_dynamic' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'capability', 'dynamic']) + if 'cap_ext_next' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'capability', 'extended-nexthop']) + if 'description' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'description', peer_config["description"]]) + if 'no_cap_nego' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'disable-capability-negotiation']) + if 'multi_hop' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'ebgp-multihop', peer_config["multi_hop"]]) + if 'local_as' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'local-as', peer_config["local_as"]]) + if 'cap_over' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'override-capability']) + if 'passive' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'passive']) + if 'password' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'password', peer_config["password"]]) + if 'port' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'port', peer_config["port"]]) + if 'remote_as' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'remote-as', peer_config["remote_as"]]) + if 'cap_strict' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'strict-capability-match']) + if 'shutdown' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'shutdown']) + if 'ttl_security' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'ttl-security', 'hops', peer_config["ttl_security"]]) + if 'update_src' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'update-source', peer_config["update_src"]]) + if 'route_map_in' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'address-family', afi, 'route-map', 'import', peer_config["route_map_in"]]) + if 'route_map_out' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'address-family', afi, 'route-map', 'export', peer_config["route_map_out"]]) + if 'pfx_list_in' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'address-family', afi, 'prefix-list', 'import', peer_config["pfx_list_in"]]) + if 'pfx_list_out' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'address-family', afi, 'prefix-list', 'export', peer_config["pfx_list_out"]]) # commit changes self.session.commit() @@ -244,11 +281,11 @@ class TestProtocolsBGP(unittest.TestCase): self.assertIn(f'router bgp {ASN}', frrconfig) for peer, peer_config in neighbor_config.items(): - if 'adv_interv' in config: + if 'adv_interv' in peer_config: self.assertIn(f' neighbor {peer} advertisement-interval {peer_config["adv_interv"]}', frrconfig) - if 'port' in config: + if 'port' in peer_config: self.assertIn(f' neighbor {peer} port {peer_config["port"]}', frrconfig) - if 'cap_strict' in config: + if 'cap_strict' in peer_config: self.assertIn(f' neighbor {peer} strict-capability-match', frrconfig) self.verify_frr_config(peer, peer_config, frrconfig) @@ -354,12 +391,12 @@ class TestProtocolsBGP(unittest.TestCase): def test_bgp_05_afi_ipv6(self): networks = { '2001:db8:100::/48' : { - }, + }, '2001:db8:200::/48' : { - }, + }, '2001:db8:300::/48' : { 'summary_only' : '', - }, + }, } # We want to redistribute ... @@ -425,5 +462,30 @@ class TestProtocolsBGP(unittest.TestCase): for prefix in listen_ranges: self.assertIn(f' bgp listen range {prefix} peer-group {peer_group}', frrconfig) + + def test_bgp_07_l2vpn_evpn(self): + vnis = ['10010', '10020', '10030'] + neighbors = ['192.0.2.10', '192.0.2.20', '192.0.2.30'] + self.session.set(base_path + ['address-family', 'l2vpn-evpn', 'advertise-all-vni']) + self.session.set(base_path + ['address-family', 'l2vpn-evpn', 'advertise-default-gw']) + self.session.set(base_path + ['address-family', 'l2vpn-evpn', 'advertise-svi-ip']) + self.session.set(base_path + ['address-family', 'l2vpn-evpn', 'flooding', 'disable']) + for vni in vnis: + self.session.set(base_path + ['address-family', 'l2vpn-evpn', 'vni', vni]) + + # commit changes + self.session.commit() + + # Verify FRR bgpd configuration + frrconfig = getFRRBGPconfig() + self.assertIn(f'router bgp {ASN}', frrconfig) + self.assertIn(f' address-family l2vpn evpn', frrconfig) + self.assertIn(f' advertise-all-vni', frrconfig) + self.assertIn(f' advertise-default-gw', frrconfig) + self.assertIn(f' advertise-svi-ip', frrconfig) + self.assertIn(f' flooding disable', frrconfig) + for vni in vnis: + self.assertIn(f' vni {vni}', frrconfig) + if __name__ == '__main__': unittest.main(verbosity=2) -- cgit v1.2.3 From 5868cbeba1bd9a4c3daaad7aa81af5c45e00cd16 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 14 Feb 2021 12:46:49 +0100 Subject: bgp: T2844: add IPv4 disable-send-community support --- data/templates/frr/bgp.frr.tmpl | 6 ++++++ interface-definitions/protocols-bgp.xml.in | 19 ------------------- smoketest/configs/bgp-small-as | 4 ++++ smoketest/scripts/cli/test_protocols_bgp.py | 18 +++++++++++++++++- src/migration-scripts/quagga/6-to-7 | 8 ++++++++ 5 files changed, 35 insertions(+), 20 deletions(-) (limited to 'data/templates/frr') diff --git a/data/templates/frr/bgp.frr.tmpl b/data/templates/frr/bgp.frr.tmpl index 62c675291..ab0f94c33 100644 --- a/data/templates/frr/bgp.frr.tmpl +++ b/data/templates/frr/bgp.frr.tmpl @@ -154,6 +154,12 @@ {% 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 diff --git a/interface-definitions/protocols-bgp.xml.in b/interface-definitions/protocols-bgp.xml.in index d7bc86aff..01463ed57 100644 --- a/interface-definitions/protocols-bgp.xml.in +++ b/interface-definitions/protocols-bgp.xml.in @@ -468,25 +468,6 @@ #include #include #include - - - Disable sending community attributes to this neighbor (IPv4) - - - - - Disable sending extended community attributes to this neighbor (IPv4) - - - - - - Disable sending standard community attributes to this neighbor (IPv4) - - - - - #include diff --git a/smoketest/configs/bgp-small-as b/smoketest/configs/bgp-small-as index 61286c324..6b953a3f6 100644 --- a/smoketest/configs/bgp-small-as +++ b/smoketest/configs/bgp-small-as @@ -345,6 +345,10 @@ protocols { } } neighbor 10.0.151.222 { + disable-send-community { + extended + standard + } address-family { ipv4-unicast { default-originate { diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py index 4c4abc600..833ca8311 100755 --- a/smoketest/scripts/cli/test_protocols_bgp.py +++ b/smoketest/scripts/cli/test_protocols_bgp.py @@ -48,6 +48,7 @@ neighbor_config = { 'local_as' : '300', 'route_map_in' : route_map_in, 'route_map_out': route_map_out, + 'no_send_comm_ext' : '', }, '192.0.2.2' : { 'remote_as' : '200', @@ -57,6 +58,7 @@ neighbor_config = { 'cap_strict' : '', 'pfx_list_in' : prefix_list_in, 'pfx_list_out' : prefix_list_out, + 'no_send_comm_std' : '', }, '192.0.2.3' : { 'description' : 'foo bar baz', @@ -78,6 +80,7 @@ neighbor_config = { 'local_as' : '300', 'route_map_in' : route_map_in, 'route_map_out': route_map_out, + 'no_send_comm_std' : '', }, '2001:db8::2' : { 'remote_as' : '456', @@ -87,6 +90,7 @@ neighbor_config = { 'cap_strict' : '', 'pfx_list_in' : prefix_list_in6, 'pfx_list_out' : prefix_list_out6, + 'no_send_comm_ext' : '', }, } @@ -108,6 +112,7 @@ peer_group_config = { 'local_as' : '300', 'pfx_list_in' : prefix_list_in, 'pfx_list_out' : prefix_list_out, + 'no_send_comm_ext' : '', }, 'baz' : { 'cap_dynamic' : '', @@ -194,7 +199,10 @@ class TestProtocolsBGP(unittest.TestCase): self.assertIn(f' neighbor {peer} prefix-list {peer_config["pfx_list_in"]} in', frrconfig) if 'pfx_list_out' in peer_config: self.assertIn(f' neighbor {peer} prefix-list {peer_config["pfx_list_out"]} out', frrconfig) - + if 'no_send_comm_std' in peer_config: + self.assertIn(f' no neighbor {peer} send-community', frrconfig) + if 'no_send_comm_ext' in peer_config: + self.assertIn(f' no neighbor {peer} send-community extended', frrconfig) def test_bgp_01_simple(self): router_id = '127.0.0.1' @@ -272,6 +280,10 @@ class TestProtocolsBGP(unittest.TestCase): self.session.set(base_path + ['neighbor', peer, 'address-family', afi, 'prefix-list', 'import', peer_config["pfx_list_in"]]) if 'pfx_list_out' in peer_config: self.session.set(base_path + ['neighbor', peer, 'address-family', afi, 'prefix-list', 'export', peer_config["pfx_list_out"]]) + if 'no_send_comm_std' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'address-family', afi, 'disable-send-community', 'standard']) + if 'no_send_comm_ext' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'address-family', afi, 'disable-send-community', 'extended']) # commit changes self.session.commit() @@ -327,6 +339,10 @@ class TestProtocolsBGP(unittest.TestCase): self.session.set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'prefix-list', 'import', config["pfx_list_in"]]) if 'pfx_list_out' in config: self.session.set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'prefix-list', 'export', config["pfx_list_out"]]) + if 'no_send_comm_std' in config: + self.session.set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'disable-send-community', 'standard']) + if 'no_send_comm_ext' in config: + self.session.set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'disable-send-community', 'extended']) # commit changes self.session.commit() diff --git a/src/migration-scripts/quagga/6-to-7 b/src/migration-scripts/quagga/6-to-7 index 3a229b5df..f7aca0d2b 100755 --- a/src/migration-scripts/quagga/6-to-7 +++ b/src/migration-scripts/quagga/6-to-7 @@ -46,6 +46,14 @@ if asn_list: if not config.exists(bgp_base + [neighbor_type]): continue for neighbor in config.list_nodes(bgp_base + [neighbor_type]): + # T2844 - add IPv4 AFI disable-send-community support + send_comm_path = bgp_base + [neighbor_type, neighbor, 'disable-send-community'] + if config.exists(send_comm_path): + new_base = bgp_base + [neighbor_type, neighbor, 'address-family', 'ipv4-unicast'] + config.set(new_base) + config.copy(send_comm_path, new_base + ['disable-send-community']) + config.delete(send_comm_path) + cap_dynamic = False for afi in ['ipv4-unicast', 'ipv6-unicast']: afi_path = bgp_base + [neighbor_type, neighbor, 'address-family', afi, 'capability', 'dynamic'] -- cgit v1.2.3 From 580baddebb933ef388c7adabf4f4971c03decf5f Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 14 Feb 2021 17:25:06 +0100 Subject: bgp: T1513: add per VNI advertise-default-gw, advertise-svi-ip options --- data/templates/frr/bgp.frr.tmpl | 8 +++++++- .../include/bgp-afi-l2vpn-common.xml.i | 14 ++++++++++++++ interface-definitions/protocols-bgp.xml.in | 21 ++++++--------------- smoketest/scripts/cli/test_protocols_bgp.py | 15 +++++++++++---- 4 files changed, 38 insertions(+), 20 deletions(-) create mode 100644 interface-definitions/include/bgp-afi-l2vpn-common.xml.i (limited to 'data/templates/frr') diff --git a/data/templates/frr/bgp.frr.tmpl b/data/templates/frr/bgp.frr.tmpl index ab0f94c33..56a54ef38 100644 --- a/data/templates/frr/bgp.frr.tmpl +++ b/data/templates/frr/bgp.frr.tmpl @@ -245,8 +245,14 @@ router bgp {{ asn }} {% endif %} {% endif %} {% if afi_config.vni is defined and afi_config.vni is not none %} -{% for vni in afi_config.vni %} +{% 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 %} exit-vni {% endfor %} {% endif %} diff --git a/interface-definitions/include/bgp-afi-l2vpn-common.xml.i b/interface-definitions/include/bgp-afi-l2vpn-common.xml.i new file mode 100644 index 000000000..11b1cf6bf --- /dev/null +++ b/interface-definitions/include/bgp-afi-l2vpn-common.xml.i @@ -0,0 +1,14 @@ + + + + Advertise All default g/w mac-ip routes in EVPN + + + + + + Advertise svi mac-ip routes in EVPN + + + + diff --git a/interface-definitions/protocols-bgp.xml.in b/interface-definitions/protocols-bgp.xml.in index 01463ed57..4af53acdc 100644 --- a/interface-definitions/protocols-bgp.xml.in +++ b/interface-definitions/protocols-bgp.xml.in @@ -228,12 +228,7 @@ - - - Advertise All default g/w mac-ip routes in EVPN - - - + #include EVPN system primary IP @@ -246,12 +241,6 @@ - - - Advertise svi mac-ip routes in EVPN - - - Auto derivation of Route Target (RFC8365) @@ -332,7 +321,7 @@ - + VXLAN Network Identifier @@ -342,9 +331,11 @@ - - + + #include + + diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py index 833ca8311..ce643a247 100755 --- a/smoketest/scripts/cli/test_protocols_bgp.py +++ b/smoketest/scripts/cli/test_protocols_bgp.py @@ -127,10 +127,13 @@ peer_group_config = { } def getFRRBGPconfig(): - return cmd(f'vtysh -c "show run" | sed -n "/router bgp {ASN}/,/^!/p"') + return cmd(f'vtysh -c "show run" | sed -n "/^router bgp {ASN}/,/^!/p"') + +def getFRRBGPVNIconfig(vni): + return cmd(f'vtysh -c "show run" | sed -n "/^ vni {vni}/,/^!/p"') def getFRRRPKIconfig(): - return cmd(f'vtysh -c "show run" | sed -n "/rpki/,/^!/p"') + return cmd(f'vtysh -c "show run" | sed -n "/^rpki/,/^!/p"') class TestProtocolsBGP(unittest.TestCase): def setUp(self): @@ -487,7 +490,8 @@ class TestProtocolsBGP(unittest.TestCase): self.session.set(base_path + ['address-family', 'l2vpn-evpn', 'advertise-svi-ip']) self.session.set(base_path + ['address-family', 'l2vpn-evpn', 'flooding', 'disable']) for vni in vnis: - self.session.set(base_path + ['address-family', 'l2vpn-evpn', 'vni', vni]) + self.session.set(base_path + ['address-family', 'l2vpn-evpn', 'vni', vni, 'advertise-default-gw']) + self.session.set(base_path + ['address-family', 'l2vpn-evpn', 'vni', vni, 'advertise-svi-ip']) # commit changes self.session.commit() @@ -501,7 +505,10 @@ class TestProtocolsBGP(unittest.TestCase): self.assertIn(f' advertise-svi-ip', frrconfig) self.assertIn(f' flooding disable', frrconfig) for vni in vnis: - self.assertIn(f' vni {vni}', frrconfig) + vniconfig = getFRRBGPVNIconfig(vni) + self.assertIn(f'vni {vni}', vniconfig) + self.assertIn(f' advertise-default-gw', vniconfig) + self.assertIn(f' advertise-svi-ip', vniconfig) if __name__ == '__main__': unittest.main(verbosity=2) -- cgit v1.2.3 From bbeafa5ed417f25ecbbc3627a346cb9294d66c68 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 14 Feb 2021 17:44:03 +0100 Subject: bgp: T2315: add CLI options for addpath-tx-(all-paths|bestpath-per-AS) * protocols bgp 65000 neighbor 192.0.2.1 address-family ipv4-unicast addpath-tx-all * protocols bgp 65000 neighbor 192.0.2.1 address-family ipv4-unicast addpath-tx-per-as * protocols bgp 65000 neighbor 2001:db8::1 address-family ipv6-unicast addpath-tx-all * protocols bgp 65000 neighbor 2001:db8::1 address-family ipv6-unicast addpath-tx-per-as --- data/templates/frr/bgp.frr.tmpl | 6 ++++++ interface-definitions/include/bgp-afi-common.xml.i | 12 ++++++++++++ smoketest/scripts/cli/test_protocols_bgp.py | 15 +++++++++++++++ 3 files changed, 33 insertions(+) (limited to 'data/templates/frr') diff --git a/data/templates/frr/bgp.frr.tmpl b/data/templates/frr/bgp.frr.tmpl index 56a54ef38..bb8131730 100644 --- a/data/templates/frr/bgp.frr.tmpl +++ b/data/templates/frr/bgp.frr.tmpl @@ -87,6 +87,12 @@ {% 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 %} diff --git a/interface-definitions/include/bgp-afi-common.xml.i b/interface-definitions/include/bgp-afi-common.xml.i index 8c483f131..1a824abfe 100644 --- a/interface-definitions/include/bgp-afi-common.xml.i +++ b/interface-definitions/include/bgp-afi-common.xml.i @@ -1,4 +1,16 @@ + + + Use addpath to advertise all paths to a neighbor + + + + + + Use addpath to advertise the bestpath per each neighboring AS + + + #include diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py index ce643a247..1de51a1fc 100755 --- a/smoketest/scripts/cli/test_protocols_bgp.py +++ b/smoketest/scripts/cli/test_protocols_bgp.py @@ -49,6 +49,7 @@ neighbor_config = { 'route_map_in' : route_map_in, 'route_map_out': route_map_out, 'no_send_comm_ext' : '', + 'addpath_all' : '', }, '192.0.2.2' : { 'remote_as' : '200', @@ -81,6 +82,7 @@ neighbor_config = { 'route_map_in' : route_map_in, 'route_map_out': route_map_out, 'no_send_comm_std' : '', + 'addpath_per_as' : '', }, '2001:db8::2' : { 'remote_as' : '456', @@ -206,6 +208,11 @@ class TestProtocolsBGP(unittest.TestCase): self.assertIn(f' no neighbor {peer} send-community', frrconfig) if 'no_send_comm_ext' in peer_config: self.assertIn(f' no neighbor {peer} send-community extended', frrconfig) + if 'addpath_all' in peer_config: + self.assertIn(f' neighbor {peer} addpath-tx-all-paths', frrconfig) + if 'addpath_per_as' in peer_config: + self.assertIn(f' neighbor {peer} addpath-tx-bestpath-per-AS', frrconfig) + def test_bgp_01_simple(self): router_id = '127.0.0.1' @@ -287,6 +294,10 @@ class TestProtocolsBGP(unittest.TestCase): self.session.set(base_path + ['neighbor', peer, 'address-family', afi, 'disable-send-community', 'standard']) if 'no_send_comm_ext' in peer_config: self.session.set(base_path + ['neighbor', peer, 'address-family', afi, 'disable-send-community', 'extended']) + if 'addpath_all' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'address-family', afi, 'addpath-tx-all']) + if 'addpath_per_as' in peer_config: + self.session.set(base_path + ['neighbor', peer, 'address-family', afi, 'addpath-tx-per-as']) # commit changes self.session.commit() @@ -346,6 +357,10 @@ class TestProtocolsBGP(unittest.TestCase): self.session.set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'disable-send-community', 'standard']) if 'no_send_comm_ext' in config: self.session.set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'disable-send-community', 'extended']) + if 'addpath_all' in config: + self.session.set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'addpath-tx-all']) + if 'addpath_per_as' in config: + self.session.set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'addpath-tx-per-as']) # commit changes self.session.commit() -- cgit v1.2.3 From df7e790df0c71c41455c9e05c0544889110dac0f Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 14 Feb 2021 17:46:18 +0100 Subject: templates: convert DOS -> UNIX line endings --- .../accel-ppp/config_chap_secrets_radius.j2 | 66 ++++---- .../accel-ppp/config_modules_auth_mode.j2 | 10 +- .../accel-ppp/config_modules_auth_protocols.j2 | 20 +-- data/templates/accel-ppp/config_modules_ipv6.j2 | 10 +- data/templates/accel-ppp/config_shaper_radius.j2 | 20 +-- data/templates/frr/static_routes_macro.j2 | 30 ++-- data/templates/squid/sg_acl.conf.tmpl | 36 ++-- data/templates/squid/squidGuard.conf.tmpl | 182 ++++++++++----------- data/templates/system/ssh_config.tmpl | 6 +- 9 files changed, 190 insertions(+), 190 deletions(-) (limited to 'data/templates/frr') diff --git a/data/templates/accel-ppp/config_chap_secrets_radius.j2 b/data/templates/accel-ppp/config_chap_secrets_radius.j2 index 4e2254b21..49af3a228 100644 --- a/data/templates/accel-ppp/config_chap_secrets_radius.j2 +++ b/data/templates/accel-ppp/config_chap_secrets_radius.j2 @@ -1,33 +1,33 @@ -{% if authentication.mode is defined and authentication.mode == 'local' %} -[chap-secrets] -chap-secrets={{ chap_secrets_file }} -{% elif authentication.mode is defined and authentication.mode == 'radius' %} -[radius] -verbose=1 -{% for server, options in authentication.radius.server.items() if not options.disable is defined %} -server={{ server }},{{ options.key }},auth-port={{ options.port }},acct-port={{ options.acct_port }},req-limit=0,fail-time={{ options.fail_time }} -{% endfor %} -{% if authentication.radius.acct_interim_jitter is defined and authentication.radius.acct_interim_jitter is not none %} -acct-interim-jitter={{ authentication.radius.acct_interim_jitter }} -{% endif %} -acct-timeout={{ authentication.radius.acct_timeout }} -timeout={{ authentication.radius.timeout }} -max-try={{ authentication.radius.max_try }} -{% if authentication.radius.nas_identifier is defined and authentication.radius.nas_identifier is not none %} -nas-identifier={{ authentication.radius.nas_identifier }} -{% endif %} -{% if authentication.radius.nas_ip_address is defined and authentication.radius.nas_ip_address is not none %} -nas-ip-address={{ authentication.radius.nas_ip_address }} -{% endif %} -{% if authentication.radius.source_address is defined and authentication.radius.source_address is not none %} -bind={{ authentication.radius.source_address }} -{% endif %} -{% if authentication.radius.dynamic_author.server is defined and authentication.radius.dynamic_author.server is not none %} -dae-server={{ authentication.radius.dynamic_author.server }}:{{ authentication.radius.dynamic_author.port }},{{ authentication.radius.dynamic_author.key }} -{% endif %} -{% endif %} -{# Both chap-secrets and radius block required the gw-ip-address #} -{% if gateway_address is defined and gateway_address is not none %} -gw-ip-address={{ gateway_address }} -{% endif %} - +{% if authentication.mode is defined and authentication.mode == 'local' %} +[chap-secrets] +chap-secrets={{ chap_secrets_file }} +{% elif authentication.mode is defined and authentication.mode == 'radius' %} +[radius] +verbose=1 +{% for server, options in authentication.radius.server.items() if not options.disable is defined %} +server={{ server }},{{ options.key }},auth-port={{ options.port }},acct-port={{ options.acct_port }},req-limit=0,fail-time={{ options.fail_time }} +{% endfor %} +{% if authentication.radius.acct_interim_jitter is defined and authentication.radius.acct_interim_jitter is not none %} +acct-interim-jitter={{ authentication.radius.acct_interim_jitter }} +{% endif %} +acct-timeout={{ authentication.radius.acct_timeout }} +timeout={{ authentication.radius.timeout }} +max-try={{ authentication.radius.max_try }} +{% if authentication.radius.nas_identifier is defined and authentication.radius.nas_identifier is not none %} +nas-identifier={{ authentication.radius.nas_identifier }} +{% endif %} +{% if authentication.radius.nas_ip_address is defined and authentication.radius.nas_ip_address is not none %} +nas-ip-address={{ authentication.radius.nas_ip_address }} +{% endif %} +{% if authentication.radius.source_address is defined and authentication.radius.source_address is not none %} +bind={{ authentication.radius.source_address }} +{% endif %} +{% if authentication.radius.dynamic_author.server is defined and authentication.radius.dynamic_author.server is not none %} +dae-server={{ authentication.radius.dynamic_author.server }}:{{ authentication.radius.dynamic_author.port }},{{ authentication.radius.dynamic_author.key }} +{% endif %} +{% endif %} +{# Both chap-secrets and radius block required the gw-ip-address #} +{% if gateway_address is defined and gateway_address is not none %} +gw-ip-address={{ gateway_address }} +{% endif %} + diff --git a/data/templates/accel-ppp/config_modules_auth_mode.j2 b/data/templates/accel-ppp/config_modules_auth_mode.j2 index 5eca76f91..e3d578b38 100644 --- a/data/templates/accel-ppp/config_modules_auth_mode.j2 +++ b/data/templates/accel-ppp/config_modules_auth_mode.j2 @@ -1,5 +1,5 @@ -{% if authentication is defined and authentication.mode is defined and authentication.mode == 'local' %} -chap-secrets -{% elif authentication is defined and authentication.mode is defined and authentication.mode == 'radius' %} -radius -{% endif %} +{% if authentication is defined and authentication.mode is defined and authentication.mode == 'local' %} +chap-secrets +{% elif authentication is defined and authentication.mode is defined and authentication.mode == 'radius' %} +radius +{% endif %} diff --git a/data/templates/accel-ppp/config_modules_auth_protocols.j2 b/data/templates/accel-ppp/config_modules_auth_protocols.j2 index e122d6c48..454d37792 100644 --- a/data/templates/accel-ppp/config_modules_auth_protocols.j2 +++ b/data/templates/accel-ppp/config_modules_auth_protocols.j2 @@ -1,10 +1,10 @@ -{% for protocol in authentication.protocols %} -{# this should be fixed in the CLI by a migrator #} -{% if protocol == 'chap' %} -auth_chap_md5 -{% elif protocol == 'mschap' %} -auth_mschap_v1 -{% else %} -auth_{{ protocol.replace('-', '_') }} -{% endif %} -{% endfor %} +{% for protocol in authentication.protocols %} +{# this should be fixed in the CLI by a migrator #} +{% if protocol == 'chap' %} +auth_chap_md5 +{% elif protocol == 'mschap' %} +auth_mschap_v1 +{% else %} +auth_{{ protocol.replace('-', '_') }} +{% endif %} +{% endfor %} diff --git a/data/templates/accel-ppp/config_modules_ipv6.j2 b/data/templates/accel-ppp/config_modules_ipv6.j2 index e9ea4924b..02740ce7c 100644 --- a/data/templates/accel-ppp/config_modules_ipv6.j2 +++ b/data/templates/accel-ppp/config_modules_ipv6.j2 @@ -1,5 +1,5 @@ -{% if ppp_options.ipv6 is defined and ppp_options.ipv6 != 'deny' %} -ipv6pool -ipv6_nd -ipv6_dhcp -{% endif %} +{% if ppp_options.ipv6 is defined and ppp_options.ipv6 != 'deny' %} +ipv6pool +ipv6_nd +ipv6_dhcp +{% endif %} diff --git a/data/templates/accel-ppp/config_shaper_radius.j2 b/data/templates/accel-ppp/config_shaper_radius.j2 index 2a6641245..8de5f5df3 100644 --- a/data/templates/accel-ppp/config_shaper_radius.j2 +++ b/data/templates/accel-ppp/config_shaper_radius.j2 @@ -1,10 +1,10 @@ -{% if authentication is defined and authentication.mode is defined and authentication.mode == 'radius' %} -{% if authentication is defined and authentication.radius is defined and authentication.radius.rate_limit is defined and authentication.radius.rate_limit.enable is defined %} -[shaper] -verbose=1 -attr={{ authentication.radius.rate_limit.attribute }} -{% if authentication.radius.rate_limit.vendor is defined and authentication.radius.rate_limit.vendor is not none %} -vendor={{ authentication.radius.rate_limit.vendor }} -{% endif %} -{% endif %} -{% endif %} +{% if authentication is defined and authentication.mode is defined and authentication.mode == 'radius' %} +{% if authentication is defined and authentication.radius is defined and authentication.radius.rate_limit is defined and authentication.radius.rate_limit.enable is defined %} +[shaper] +verbose=1 +attr={{ authentication.radius.rate_limit.attribute }} +{% if authentication.radius.rate_limit.vendor is defined and authentication.radius.rate_limit.vendor is not none %} +vendor={{ authentication.radius.rate_limit.vendor }} +{% endif %} +{% endif %} +{% endif %} diff --git a/data/templates/frr/static_routes_macro.j2 b/data/templates/frr/static_routes_macro.j2 index aadb2805e..b24232ef3 100644 --- a/data/templates/frr/static_routes_macro.j2 +++ b/data/templates/frr/static_routes_macro.j2 @@ -1,15 +1,15 @@ -{% macro static_routes(ip_ipv6, prefix, prefix_config, table=None) %} -{% if prefix_config.blackhole is defined %} -{{ ip_ipv6 }} route {{ prefix }} blackhole {{ prefix_config.blackhole.distance if prefix_config.blackhole.distance is defined }} {{ 'tag ' + prefix_config.blackhole.tag if prefix_config.blackhole.tag is defined }} {{ 'table ' + table if table is defined and table is not none }} -{% endif %} -{% if prefix_config.interface is defined and prefix_config.interface is not none %} -{% for interface, interface_config in prefix_config.interface.items() if interface_config.disable is not defined %} -{{ ip_ipv6 }} route {{ prefix }} {{ interface }} {{ interface_config.distance if interface_config.distance is defined }} {{ 'nexthop-vrf ' + interface_config.vrf if interface_config.vrf is defined }} {{ 'table ' + table if table is defined and table is not none }} -{% endfor %} -{% endif %} -{% if prefix_config.next_hop is defined and prefix_config.next_hop is not none %} -{% for next_hop, next_hop_config in prefix_config.next_hop.items() if next_hop_config.disable is not defined %} -{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ next_hop_config.interface if next_hop_config.interface is defined }} {{ next_hop_config.distance if next_hop_config.distance is defined }} {{ 'nexthop-vrf ' + next_hop_config.vrf if next_hop_config.vrf is defined }} {{ 'table ' + table if table is defined and table is not none }} -{% endfor %} -{% endif %} -{% endmacro %} +{% macro static_routes(ip_ipv6, prefix, prefix_config, table=None) %} +{% if prefix_config.blackhole is defined %} +{{ ip_ipv6 }} route {{ prefix }} blackhole {{ prefix_config.blackhole.distance if prefix_config.blackhole.distance is defined }} {{ 'tag ' + prefix_config.blackhole.tag if prefix_config.blackhole.tag is defined }} {{ 'table ' + table if table is defined and table is not none }} +{% endif %} +{% if prefix_config.interface is defined and prefix_config.interface is not none %} +{% for interface, interface_config in prefix_config.interface.items() if interface_config.disable is not defined %} +{{ ip_ipv6 }} route {{ prefix }} {{ interface }} {{ interface_config.distance if interface_config.distance is defined }} {{ 'nexthop-vrf ' + interface_config.vrf if interface_config.vrf is defined }} {{ 'table ' + table if table is defined and table is not none }} +{% endfor %} +{% endif %} +{% if prefix_config.next_hop is defined and prefix_config.next_hop is not none %} +{% for next_hop, next_hop_config in prefix_config.next_hop.items() if next_hop_config.disable is not defined %} +{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ next_hop_config.interface if next_hop_config.interface is defined }} {{ next_hop_config.distance if next_hop_config.distance is defined }} {{ 'nexthop-vrf ' + next_hop_config.vrf if next_hop_config.vrf is defined }} {{ 'table ' + table if table is defined and table is not none }} +{% endfor %} +{% endif %} +{% endmacro %} diff --git a/data/templates/squid/sg_acl.conf.tmpl b/data/templates/squid/sg_acl.conf.tmpl index cb1c3ccb0..ce72b173a 100644 --- a/data/templates/squid/sg_acl.conf.tmpl +++ b/data/templates/squid/sg_acl.conf.tmpl @@ -1,18 +1,18 @@ -### generated by service_webproxy.py ### -dbhome {{ squidguard_db_dir }} - -dest {{ category }}-{{ rule }} { -{% if list_type == 'domains' %} - domainlist {{ category }}/domains -{% elif list_type == 'urls' %} - urllist {{ category }}/urls -{% elif list_type == 'expressions' %} - expressionlist {{ category }}/expressions -{% endif %} -} - -acl { - default { - pass all - } -} +### generated by service_webproxy.py ### +dbhome {{ squidguard_db_dir }} + +dest {{ category }}-{{ rule }} { +{% if list_type == 'domains' %} + domainlist {{ category }}/domains +{% elif list_type == 'urls' %} + urllist {{ category }}/urls +{% elif list_type == 'expressions' %} + expressionlist {{ category }}/expressions +{% endif %} +} + +acl { + default { + pass all + } +} diff --git a/data/templates/squid/squidGuard.conf.tmpl b/data/templates/squid/squidGuard.conf.tmpl index 74de3a651..f530d1072 100644 --- a/data/templates/squid/squidGuard.conf.tmpl +++ b/data/templates/squid/squidGuard.conf.tmpl @@ -1,91 +1,91 @@ -### generated by service_webproxy.py ### - -{% macro sg_rule(category, log, db_dir) %} -{% set expressions = db_dir + '/' + category + '/expressions' %} -dest {{ category }}-default { - domainlist {{ category }}/domains - urllist {{ category }}/urls -{% if expressions | is_file %} - expressionlist {{ category }}/expressions -{% endif %} -{% if log is defined %} - log blacklist.log -{% endif %} -} -{% endmacro %} - -{% if url_filtering is defined and url_filtering.disable is not defined %} -{% if url_filtering.squidguard is defined and url_filtering.squidguard is not none %} -{% set sg_config = url_filtering.squidguard %} -{% set acl = namespace(value='local-ok-default') %} -{% set acl.value = acl.value + ' !in-addr' if sg_config.allow_ipaddr_url is not defined else acl.value %} -dbhome {{ squidguard_db_dir }} -logdir /var/log/squid - -rewrite safesearch { - s@(.*\.google\..*/(custom|search|images|groups|news)?.*q=.*)@\1\&safe=active@i - s@(.*\..*/yandsearch?.*text=.*)@\1\&fyandex=1@i - s@(.*\.yahoo\..*/search.*p=.*)@\1\&vm=r@i - s@(.*\.live\..*/.*q=.*)@\1\&adlt=strict@i - s@(.*\.msn\..*/.*q=.*)@\1\&adlt=strict@i - s@(.*\.bing\..*/search.*q=.*)@\1\&adlt=strict@i - log rewrite.log -} - -{% if sg_config.local_ok is defined and sg_config.local_ok is not none %} -{% set acl.value = acl.value + ' local-ok-default' %} -dest local-ok-default { - domainlist local-ok-default/domains -} -{% endif %} -{% if sg_config.local_ok_url is defined and sg_config.local_ok_url is not none %} -{% set acl.value = acl.value + ' local-ok-url-default' %} -dest local-ok-url-default { - urllist local-ok-url-default/urls -} -{% endif %} -{% if sg_config.local_block is defined and sg_config.local_block is not none %} -{% set acl.value = acl.value + ' !local-block-default' %} -dest local-block-default { - domainlist local-block-default/domains -} -{% endif %} -{% if sg_config.local_block_url is defined and sg_config.local_block_url is not none %} -{% set acl.value = acl.value + ' !local-block-url-default' %} -dest local-block-url-default { - urllist local-block-url-default/urls -} -{% endif %} -{% if sg_config.local_block_keyword is defined and sg_config.local_block_keyword is not none %} -{% set acl.value = acl.value + ' !local-block-keyword-default' %} -dest local-block-keyword-default { - expressionlist local-block-keyword-default/expressions -} -{% endif %} - -{% if sg_config.block_category is defined and sg_config.block_category is not none %} -{% for category in sg_config.block_category %} -{{ sg_rule(category, sg_config.log, squidguard_db_dir) }} -{% set acl.value = acl.value + ' !' + category + '-default' %} -{% endfor %} -{% endif %} -{% if sg_config.allow_category is defined and sg_config.allow_category is not none %} -{% for category in sg_config.allow_category %} -{{ sg_rule(category, False, squidguard_db_dir) }} -{% set acl.value = acl.value + ' ' + category + '-default' %} -{% endfor %} -{% endif %} -acl { - default { -{% if sg_config.enable_safe_search is defined %} - rewrite safesearch -{% endif %} - pass {{ acl.value }} {{ 'none' if sg_config.default_action is defined and sg_config.default_action == 'block' else 'allow' }} - redirect 302:http://{{ sg_config.redirect_url }} -{% if sg_config.log is defined and sg_config.log is not none %} - log blacklist.log -{% endif %} - } -} -{% endif %} -{% endif %} +### generated by service_webproxy.py ### + +{% macro sg_rule(category, log, db_dir) %} +{% set expressions = db_dir + '/' + category + '/expressions' %} +dest {{ category }}-default { + domainlist {{ category }}/domains + urllist {{ category }}/urls +{% if expressions | is_file %} + expressionlist {{ category }}/expressions +{% endif %} +{% if log is defined %} + log blacklist.log +{% endif %} +} +{% endmacro %} + +{% if url_filtering is defined and url_filtering.disable is not defined %} +{% if url_filtering.squidguard is defined and url_filtering.squidguard is not none %} +{% set sg_config = url_filtering.squidguard %} +{% set acl = namespace(value='local-ok-default') %} +{% set acl.value = acl.value + ' !in-addr' if sg_config.allow_ipaddr_url is not defined else acl.value %} +dbhome {{ squidguard_db_dir }} +logdir /var/log/squid + +rewrite safesearch { + s@(.*\.google\..*/(custom|search|images|groups|news)?.*q=.*)@\1\&safe=active@i + s@(.*\..*/yandsearch?.*text=.*)@\1\&fyandex=1@i + s@(.*\.yahoo\..*/search.*p=.*)@\1\&vm=r@i + s@(.*\.live\..*/.*q=.*)@\1\&adlt=strict@i + s@(.*\.msn\..*/.*q=.*)@\1\&adlt=strict@i + s@(.*\.bing\..*/search.*q=.*)@\1\&adlt=strict@i + log rewrite.log +} + +{% if sg_config.local_ok is defined and sg_config.local_ok is not none %} +{% set acl.value = acl.value + ' local-ok-default' %} +dest local-ok-default { + domainlist local-ok-default/domains +} +{% endif %} +{% if sg_config.local_ok_url is defined and sg_config.local_ok_url is not none %} +{% set acl.value = acl.value + ' local-ok-url-default' %} +dest local-ok-url-default { + urllist local-ok-url-default/urls +} +{% endif %} +{% if sg_config.local_block is defined and sg_config.local_block is not none %} +{% set acl.value = acl.value + ' !local-block-default' %} +dest local-block-default { + domainlist local-block-default/domains +} +{% endif %} +{% if sg_config.local_block_url is defined and sg_config.local_block_url is not none %} +{% set acl.value = acl.value + ' !local-block-url-default' %} +dest local-block-url-default { + urllist local-block-url-default/urls +} +{% endif %} +{% if sg_config.local_block_keyword is defined and sg_config.local_block_keyword is not none %} +{% set acl.value = acl.value + ' !local-block-keyword-default' %} +dest local-block-keyword-default { + expressionlist local-block-keyword-default/expressions +} +{% endif %} + +{% if sg_config.block_category is defined and sg_config.block_category is not none %} +{% for category in sg_config.block_category %} +{{ sg_rule(category, sg_config.log, squidguard_db_dir) }} +{% set acl.value = acl.value + ' !' + category + '-default' %} +{% endfor %} +{% endif %} +{% if sg_config.allow_category is defined and sg_config.allow_category is not none %} +{% for category in sg_config.allow_category %} +{{ sg_rule(category, False, squidguard_db_dir) }} +{% set acl.value = acl.value + ' ' + category + '-default' %} +{% endfor %} +{% endif %} +acl { + default { +{% if sg_config.enable_safe_search is defined %} + rewrite safesearch +{% endif %} + pass {{ acl.value }} {{ 'none' if sg_config.default_action is defined and sg_config.default_action == 'block' else 'allow' }} + redirect 302:http://{{ sg_config.redirect_url }} +{% if sg_config.log is defined and sg_config.log is not none %} + log blacklist.log +{% endif %} + } +} +{% endif %} +{% endif %} diff --git a/data/templates/system/ssh_config.tmpl b/data/templates/system/ssh_config.tmpl index 509bd5479..abc03f069 100644 --- a/data/templates/system/ssh_config.tmpl +++ b/data/templates/system/ssh_config.tmpl @@ -1,3 +1,3 @@ -{% if ssh_client is defined and ssh_client.source_address is defined and ssh_client.source_address is not none %} -BindAddress {{ ssh_client.source_address }} -{% endif %} +{% if ssh_client is defined and ssh_client.source_address is defined and ssh_client.source_address is not none %} +BindAddress {{ ssh_client.source_address }} +{% endif %} -- cgit v1.2.3 From 3a32c507134c4599f343dda54ccf4e80ea62def4 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 14 Feb 2021 14:23:25 +0100 Subject: bfd: T3310: migrate to get_config_dict() and FRR reload --- data/configd-include.json | 1 + data/templates/frr/bfd.frr.tmpl | 37 +++--- interface-definitions/protocols-bfd.xml.in | 6 + src/conf_mode/protocols_bfd.py | 207 ++++++++--------------------- 4 files changed, 82 insertions(+), 169 deletions(-) (limited to 'data/templates/frr') diff --git a/data/configd-include.json b/data/configd-include.json index e50dbf1b2..aabd7232e 100644 --- a/data/configd-include.json +++ b/data/configd-include.json @@ -32,6 +32,7 @@ "nat66.py", "ntp.py", "policy-local-route.py", +"protocols_bfd.py", "protocols_bgp.py", "protocols_igmp.py", "protocols_isis.py", diff --git a/data/templates/frr/bfd.frr.tmpl b/data/templates/frr/bfd.frr.tmpl index 9e5ad3379..921d9b0bc 100644 --- a/data/templates/frr/bfd.frr.tmpl +++ b/data/templates/frr/bfd.frr.tmpl @@ -1,22 +1,23 @@ ! bfd -{% for peer in old_peers %} - no peer {{ peer.remote }}{% if peer.multihop %} multihop{% endif %}{% if peer.src_addr %} local-address {{ peer.src_addr }}{% endif %}{% if peer.src_if %} interface {{ peer.src_if }}{% endif %} - -{% endfor %} -! -{% for peer in new_peers %} - peer {{ peer.remote }}{% if peer.multihop %} multihop{% endif %}{% if peer.src_addr %} local-address {{ peer.src_addr }}{% endif %}{% if peer.src_if %} interface {{ peer.src_if }}{% endif %} - - detect-multiplier {{ peer.multiplier }} - receive-interval {{ peer.rx_interval }} - transmit-interval {{ peer.tx_interval }} -{% if peer.echo_mode %} - echo-mode -{% endif %} -{% if peer.echo_interval != '' %} - echo-interval {{ peer.echo_interval }} +{% if peer is defined and peer is not none %} +{% for peer_name, peer_config in peer.items() %} + peer {{ peer_name }}{{ ' multihop' if peer_config.multihop is defined }}{{ ' local-address ' + peer_config.source.address if peer_config.source is defined and peer_config.source.address is defined }}{{ ' interface ' + peer_config.source.interface if peer_config.source is defined and peer_config.source.interface is defined }} + detect-multiplier {{ peer_config.interval.multiplier }} + receive-interval {{ peer_config.interval.receive }} + transmit-interval {{ peer_config.interval.transmit }} +{% if peer_config.interval.echo_interval is defined and peer_config.interval.echo_interval is not none %} + echo-interval {{ peer_config.interval.echo_interval }} +{% endif %} +{% if peer_config.echo_mode is defined %} + echo-mode +{% endif %} +{% if peer_config.shutdown is defined %} + shutdown +{% else %} + no shutdown +{% endif %} + ! +{% endfor %} {% endif %} - {% if not peer.shutdown %}no {% endif %}shutdown -{% endfor %} ! diff --git a/interface-definitions/protocols-bfd.xml.in b/interface-definitions/protocols-bfd.xml.in index 8900e7955..6f82a5c2b 100644 --- a/interface-definitions/protocols-bfd.xml.in +++ b/interface-definitions/protocols-bfd.xml.in @@ -42,6 +42,9 @@ Local address to bind our peer listener to + + + ipv4 Local IPv4 address used to connect to the peer @@ -74,6 +77,7 @@ + 300 @@ -86,6 +90,7 @@ + 300 @@ -98,6 +103,7 @@ + 3 diff --git a/src/conf_mode/protocols_bfd.py b/src/conf_mode/protocols_bfd.py index d1e551cad..7737c6aa1 100755 --- a/src/conf_mode/protocols_bfd.py +++ b/src/conf_mode/protocols_bfd.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2020 VyOS maintainers and contributors +# Copyright (C) 2019-2021 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 @@ -17,191 +17,96 @@ import os from sys import exit -from copy import deepcopy from vyos.config import Config +from vyos.configdict import dict_merge from vyos.template import is_ipv6 -from vyos.template import render +from vyos.template import render_to_string from vyos.util import call from vyos.validate import is_ipv6_link_local +from vyos.xml import defaults from vyos import ConfigError +from vyos import frr from vyos import airbag airbag.enable() -config_file = r'/tmp/bfd.frr' - -default_config_data = { - 'new_peers': [], - 'old_peers' : [] -} - -# get configuration for BFD peer from proposed or effective configuration -def get_bfd_peer_config(peer, conf_mode="proposed"): - conf = Config() - conf.set_level('protocols bfd peer {0}'.format(peer)) - - bfd_peer = { - 'remote': peer, - 'shutdown': False, - 'src_if': '', - 'src_addr': '', - 'multiplier': '3', - 'rx_interval': '300', - 'tx_interval': '300', - 'multihop': False, - 'echo_interval': '', - 'echo_mode': False, - } - - # Check if individual peer is disabled - if conf_mode == "effective" and conf.exists_effective('shutdown'): - bfd_peer['shutdown'] = True - if conf_mode == "proposed" and conf.exists('shutdown'): - bfd_peer['shutdown'] = True - - # Check if peer has a local source interface configured - if conf_mode == "effective" and conf.exists_effective('source interface'): - bfd_peer['src_if'] = conf.return_effective_value('source interface') - if conf_mode == "proposed" and conf.exists('source interface'): - bfd_peer['src_if'] = conf.return_value('source interface') - - # Check if peer has a local source address configured - this is mandatory for IPv6 - if conf_mode == "effective" and conf.exists_effective('source address'): - bfd_peer['src_addr'] = conf.return_effective_value('source address') - if conf_mode == "proposed" and conf.exists('source address'): - bfd_peer['src_addr'] = conf.return_value('source address') - - # Tell BFD daemon that we should expect packets with TTL less than 254 - # (because it will take more than one hop) and to listen on the multihop - # port (4784) - if conf_mode == "effective" and conf.exists_effective('multihop'): - bfd_peer['multihop'] = True - if conf_mode == "proposed" and conf.exists('multihop'): - bfd_peer['multihop'] = True - - # Configures the minimum interval that this system is capable of receiving - # control packets. The default value is 300 milliseconds. - if conf_mode == "effective" and conf.exists_effective('interval receive'): - bfd_peer['rx_interval'] = conf.return_effective_value('interval receive') - if conf_mode == "proposed" and conf.exists('interval receive'): - bfd_peer['rx_interval'] = conf.return_value('interval receive') - - # The minimum transmission interval (less jitter) that this system wants - # to use to send BFD control packets. - if conf_mode == "effective" and conf.exists_effective('interval transmit'): - bfd_peer['tx_interval'] = conf.return_effective_value('interval transmit') - if conf_mode == "proposed" and conf.exists('interval transmit'): - bfd_peer['tx_interval'] = conf.return_value('interval transmit') - - # Configures the detection multiplier to determine packet loss. The remote - # transmission interval will be multiplied by this value to determine the - # connection loss detection timer. The default value is 3. - if conf_mode == "effective" and conf.exists_effective('interval multiplier'): - bfd_peer['multiplier'] = conf.return_effective_value('interval multiplier') - if conf_mode == "proposed" and conf.exists('interval multiplier'): - bfd_peer['multiplier'] = conf.return_value('interval multiplier') - - # Configures the minimal echo receive transmission interval that this system is capable of handling - if conf_mode == "effective" and conf.exists_effective('interval echo-interval'): - bfd_peer['echo_interval'] = conf.return_effective_value('interval echo-interval') - if conf_mode == "proposed" and conf.exists('interval echo-interval'): - bfd_peer['echo_interval'] = conf.return_value('interval echo-interval') - - # Enables or disables the echo transmission mode - if conf_mode == "effective" and conf.exists_effective('echo-mode'): - bfd_peer['echo_mode'] = True - if conf_mode == "proposed" and conf.exists('echo-mode'): - bfd_peer['echo_mode'] = True - - return bfd_peer - -def get_config(): - bfd = deepcopy(default_config_data) - conf = Config() - if not (conf.exists('protocols bfd') or conf.exists_effective('protocols bfd')): - return None +def get_config(config=None): + if config: + conf = config else: - conf.set_level('protocols bfd') - - # as we have to use vtysh to talk to FRR we also need to know - # which peers are gone due to a config removal - thus we read in - # all peers (active or to delete) - for peer in conf.list_effective_nodes('peer'): - bfd['old_peers'].append(get_bfd_peer_config(peer, "effective")) - - for peer in conf.list_nodes('peer'): - bfd['new_peers'].append(get_bfd_peer_config(peer)) - - # find deleted peers - set_new_peers = set(conf.list_nodes('peer')) - set_old_peers = set(conf.list_effective_nodes('peer')) - bfd['deleted_peers'] = set_old_peers - set_new_peers + conf = Config() + base = ['protocols', 'bfd'] + bfd = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + + # Bail out early if configuration tree does not exist + if not conf.exists(base): + return bfd + + if 'peer' in bfd: + # We have gathered the dict representation of the CLI, but there are + # default options which we need to update into the dictionary retrived. + # XXX: T2665: we currently have no nice way for defaults under tag + # nodes, thus we load the defaults "by hand" + default_values = defaults(base + ['peer']) + for peer in bfd['peer']: + bfd['peer'][peer] = dict_merge(default_values, bfd['peer'][peer]) return bfd def verify(bfd): - if bfd is None: + if not bfd or 'peer' not in bfd: return None - # some variables to use later - conf = Config() - - for peer in bfd['new_peers']: + for peer, peer_config in bfd['peer'].items(): # IPv6 link local peers require an explicit local address/interface - if is_ipv6_link_local(peer['remote']): - if not (peer['src_if'] and peer['src_addr']): + if is_ipv6_link_local(peer): + if 'source' not in peer_config or len(peer_config['source'] < 2): raise ConfigError('BFD IPv6 link-local peers require explicit local address and interface setting') # IPv6 peers require an explicit local address - if is_ipv6(peer['remote']): - if not peer['src_addr']: + if is_ipv6(peer): + if 'source' not in peer_config or 'address' not in peer_config['source']: raise ConfigError('BFD IPv6 peers require explicit local address setting') - # multihop require source address - if peer['multihop'] and not peer['src_addr']: - raise ConfigError('Multihop require source address') + if 'multihop' in peer_config: + # multihop require source address + if 'source' not in peer_config or 'address' not in peer_config['source']: + raise ConfigError('BFD multihop require source address') - # multihop and echo-mode cannot be used together - if peer['multihop'] and peer['echo_mode']: - raise ConfigError('Multihop and echo-mode cannot be used together') + # multihop and echo-mode cannot be used together + if 'echo_mode' in peer_config: + raise ConfigError('Multihop and echo-mode cannot be used together') - # multihop doesn't accept interface names - if peer['multihop'] and peer['src_if']: - raise ConfigError('Multihop and source interface cannot be used together') + # multihop doesn't accept interface names + if 'source' in peer_config and 'interface' in peer_config['source']: + raise ConfigError('Multihop and source interface cannot be used together') # echo interval can be configured only with enabled echo-mode - if peer['echo_interval'] != '' and not peer['echo_mode']: + if 'interval' in peer_config and 'echo_interval' in peer_config['interval'] and 'echo_mode' not in peer_config: raise ConfigError('echo-interval can be configured only with enabled echo-mode') - # check if we deleted peers are not used in configuration - if conf.exists('protocols bgp'): - bgp_as = conf.list_nodes('protocols bgp')[0] - - # check BGP neighbors - for peer in bfd['deleted_peers']: - if conf.exists('protocols bgp {0} neighbor {1} bfd'.format(bgp_as, peer)): - raise ConfigError('Cannot delete BFD peer {0}: it is used in BGP configuration'.format(peer)) - if conf.exists('protocols bgp {0} neighbor {1} peer-group'.format(bgp_as, peer)): - peer_group = conf.return_value('protocols bgp {0} neighbor {1} peer-group'.format(bgp_as, peer)) - if conf.exists('protocols bgp {0} peer-group {1} bfd'.format(bgp_as, peer_group)): - raise ConfigError('Cannot delete BFD peer {0}: it belongs to BGP peer-group {1} with enabled BFD'.format(peer, peer_group)) - return None def generate(bfd): - if bfd is None: + if not bfd: + bfd['new_frr_config'] = '' return None - render(config_file, 'frr/bfd.frr.tmpl', bfd) - return None + bfd['new_frr_config'] = render_to_string('frr/bfd.frr.tmpl', bfd) def apply(bfd): - if bfd is None: - return None - - call("vtysh -d bfdd -f " + config_file) - if os.path.exists(config_file): - os.remove(config_file) + # Save original configuration prior to starting any commit actions + frr_cfg = frr.FRRConfig() + frr_cfg.load_configuration() + frr_cfg.modify_section('bfd', '') + frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', bfd['new_frr_config']) + frr_cfg.commit_configuration() + + # If FRR config is blank, rerun the blank commit x times due to frr-reload + # behavior/bug not properly clearing out on one commit. + if bfd['new_frr_config'] == '': + for a in range(5): + frr_cfg.commit_configuration() return None -- cgit v1.2.3 From 3d3d09d6e5d7350b09709447ed4d7a7790e09b81 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 15 Feb 2021 20:16:02 +0100 Subject: bfd: T3310: implement peer profile support --- data/templates/frr/bfd.frr.tmpl | 29 ++++++- interface-definitions/include/bfd-common.xml.i | 72 ++++++++++++++++++ interface-definitions/protocols-bfd.xml.in | 100 +++++++------------------ smoketest/scripts/cli/test_protocols_bfd.py | 69 +++++++++++++++-- src/conf_mode/protocols_bfd.py | 71 +++++++++--------- 5 files changed, 223 insertions(+), 118 deletions(-) create mode 100644 interface-definitions/include/bfd-common.xml.i (limited to 'data/templates/frr') diff --git a/data/templates/frr/bfd.frr.tmpl b/data/templates/frr/bfd.frr.tmpl index 921d9b0bc..3b3d13f9d 100644 --- a/data/templates/frr/bfd.frr.tmpl +++ b/data/templates/frr/bfd.frr.tmpl @@ -1,15 +1,35 @@ ! bfd +{% if profile is defined and profile is not none %} +{% for profile_name, profile_config in profile.items() %} + profile {{ profile_name }} + detect-multiplier {{ profile_config.interval.multiplier }} + receive-interval {{ profile_config.interval.receive }} + transmit-interval {{ profile_config.interval.transmit }} +{% if profile_config.interval['echo-interval'] is defined and profile_config.interval['echo-interval'] is not none %} + echo-interval {{ profile_config.interval['echo-interval'] }} +{% endif %} +{% if profile_config['echo-mode'] is defined %} + echo-mode +{% endif %} +{% if profile_config.shutdown is defined %} + shutdown +{% else %} + no shutdown +{% endif %} + exit +{% endfor %} +{% endif %} {% if peer is defined and peer is not none %} {% for peer_name, peer_config in peer.items() %} peer {{ peer_name }}{{ ' multihop' if peer_config.multihop is defined }}{{ ' local-address ' + peer_config.source.address if peer_config.source is defined and peer_config.source.address is defined }}{{ ' interface ' + peer_config.source.interface if peer_config.source is defined and peer_config.source.interface is defined }} detect-multiplier {{ peer_config.interval.multiplier }} receive-interval {{ peer_config.interval.receive }} transmit-interval {{ peer_config.interval.transmit }} -{% if peer_config.interval.echo_interval is defined and peer_config.interval.echo_interval is not none %} - echo-interval {{ peer_config.interval.echo_interval }} +{% if peer_config.interval['echo-interval'] is defined and peer_config.interval['echo-interval'] is not none %} + echo-interval {{ peer_config.interval['echo-interval'] }} {% endif %} -{% if peer_config.echo_mode is defined %} +{% if peer_config['echo-mode'] is defined %} echo-mode {% endif %} {% if peer_config.shutdown is defined %} @@ -17,7 +37,8 @@ bfd {% else %} no shutdown {% endif %} - ! + exit {% endfor %} {% endif %} + exit ! diff --git a/interface-definitions/include/bfd-common.xml.i b/interface-definitions/include/bfd-common.xml.i new file mode 100644 index 000000000..ff73e4b20 --- /dev/null +++ b/interface-definitions/include/bfd-common.xml.i @@ -0,0 +1,72 @@ + + + + Enables the echo transmission mode + + + + + + Configure timer intervals + + + + + Minimum interval of receiving control packets + + 10-60000 + Interval in milliseconds + + + + + + 300 + + + + Minimum interval of transmitting control packets + + 10-60000 + Interval in milliseconds + + + + + + 300 + + + + Multiplier to determine packet loss + + 2-255 + Remote transmission interval will be multiplied by this value + + + + + + 3 + + + + Echo receive transmission interval + + 10-60000 + The minimal echo receive transmission interval that this system is capable of handling + + + + + + + + + + + Disable this peer + + + + diff --git a/interface-definitions/protocols-bfd.xml.in b/interface-definitions/protocols-bfd.xml.in index 6f82a5c2b..cc3c3bf12 100644 --- a/interface-definitions/protocols-bfd.xml.in +++ b/interface-definitions/protocols-bfd.xml.in @@ -11,7 +11,7 @@ - Configures a new BFD peer to listen and talk to + Configures BFD peer to listen and talk to ipv4 BFD peer IPv4 address @@ -26,6 +26,18 @@ + + + Use settings from BFD profile + + protocols bfd profile + + + txt + BFD profile name + + + Bind listener to specified interface/address, mandatory for IPv6 @@ -61,82 +73,28 @@ - - - Configure timer intervals - - - - - Minimum interval of receiving control packets - - 10-60000 - Interval in milliseconds - - - - - - 300 - - - - Minimum interval of transmitting control packets - - 10-60000 - Interval in milliseconds - - - - - - 300 - - - - Multiplier to determine packet loss - - 2-255 - Remote transmission interval will be multiplied by this value - - - - - - 3 - - - - Echo receive transmission interval - - 10-60000 - The minimal echo receive transmission interval that this system is capable of handling - - - - - - - - - - - Disable this peer - - - + #include Allow this BFD peer to not be directly connected - - - Enables the echo transmission mode - - - + + + + + Configure BFD profile used by individual peer + + txt + Name of BFD profile + + + ^[-_a-zA-Z0-9]{1,32}$ + + + + #include diff --git a/smoketest/scripts/cli/test_protocols_bfd.py b/smoketest/scripts/cli/test_protocols_bfd.py index 996a54a9d..80e5daa7c 100755 --- a/smoketest/scripts/cli/test_protocols_bfd.py +++ b/smoketest/scripts/cli/test_protocols_bfd.py @@ -26,7 +26,7 @@ PROCESS_NAME = 'bfdd' base_path = ['protocols', 'bfd'] dum_if = 'dum1001' -neighbor_config = { +peers = { '192.0.2.10' : { 'intv_rx' : '500', 'intv_tx' : '600', @@ -36,7 +36,7 @@ neighbor_config = { '192.0.2.20' : { 'echo_mode' : '', 'intv_echo' : '100', - 'intv_mult' : '111', + 'intv_mult' : '100', 'intv_rx' : '222', 'intv_tx' : '333', 'shutdown' : '', @@ -52,20 +52,35 @@ neighbor_config = { }, } +profiles = { + 'foo' : { + 'echo_mode' : '', + 'intv_echo' : '100', + 'intv_mult' : '101', + 'intv_rx' : '222', + 'intv_tx' : '333', + 'shutdown' : '', + }, + 'bar' : { + 'intv_mult' : '102', + 'intv_rx' : '444', + }, +} + def getFRRconfig(): return cmd('vtysh -c "show run" | sed -n "/^bfd/,/^!/p"') def getBFDPeerconfig(peer): return cmd(f'vtysh -c "show run" | sed -n "/^ {peer}/,/^!/p"') +def getBFDProfileconfig(profile): + return cmd(f'vtysh -c "show run" | sed -n "/^ {profile}/,/^!/p"') + class TestProtocolsBFD(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) - self.session.set(['interfaces', 'dummy', dum_if, 'address', '192.0.2.1/24']) - self.session.set(['interfaces', 'dummy', dum_if, 'address', '2001:db8::1/64']) def tearDown(self): - self.session.delete(['interfaces', 'dummy', dum_if]) self.session.delete(base_path) self.session.commit() del self.session @@ -73,8 +88,8 @@ class TestProtocolsBFD(unittest.TestCase): # Check for running process self.assertTrue(process_named_running(PROCESS_NAME)) - def test_bfd_simple(self): - for peer, peer_config in neighbor_config.items(): + def test_bfd_peer(self): + for peer, peer_config in peers.items(): if 'echo_mode' in peer_config: self.session.set(base_path + ['peer', peer, 'echo-mode']) if 'intv_echo' in peer_config: @@ -99,7 +114,7 @@ class TestProtocolsBFD(unittest.TestCase): # Verify FRR bgpd configuration frrconfig = getFRRconfig() - for peer, peer_config in neighbor_config.items(): + for peer, peer_config in peers.items(): tmp = f'peer {peer}' if 'multihop' in peer_config: tmp += f' multihop' @@ -124,5 +139,43 @@ class TestProtocolsBFD(unittest.TestCase): if 'shutdown' not in peer_config: self.assertIn(f' no shutdown', peerconfig) + def test_bfd_profile(self): + peer = '192.0.2.10' + + for profile, profile_config in profiles.items(): + if 'echo_mode' in profile_config: + self.session.set(base_path + ['profile', profile, 'echo-mode']) + if 'intv_echo' in profile_config: + self.session.set(base_path + ['profile', profile, 'interval', 'echo-interval', profile_config["intv_echo"]]) + if 'intv_mult' in profile_config: + self.session.set(base_path + ['profile', profile, 'interval', 'multiplier', profile_config["intv_mult"]]) + if 'intv_rx' in profile_config: + self.session.set(base_path + ['profile', profile, 'interval', 'receive', profile_config["intv_rx"]]) + if 'intv_tx' in profile_config: + self.session.set(base_path + ['profile', profile, 'interval', 'transmit', profile_config["intv_tx"]]) + if 'shutdown' in profile_config: + self.session.set(base_path + ['profile', profile, 'shutdown']) + + self.session.set(base_path + ['peer', peer, 'profile', list(profiles)[0]]) + + # commit changes + self.session.commit() + + # Verify FRR bgpd configuration + for profile, profile_config in profiles.items(): + config = getBFDProfileconfig(f'profile {profile}') + if 'echo_mode' in profile_config: + self.assertIn(f' echo-mode', config) + if 'intv_echo' in profile_config: + self.assertIn(f' echo-interval {profile_config["intv_echo"]}', config) + if 'intv_mult' in profile_config: + self.assertIn(f' detect-multiplier {profile_config["intv_mult"]}', config) + if 'intv_rx' in profile_config: + self.assertIn(f' receive-interval {profile_config["intv_rx"]}', config) + if 'intv_tx' in profile_config: + self.assertIn(f' transmit-interval {profile_config["intv_tx"]}', config) + if 'shutdown' not in profile_config: + self.assertIn(f' no shutdown', config) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/src/conf_mode/protocols_bfd.py b/src/conf_mode/protocols_bfd.py index 7737c6aa1..a43eed504 100755 --- a/src/conf_mode/protocols_bfd.py +++ b/src/conf_mode/protocols_bfd.py @@ -36,54 +36,55 @@ def get_config(config=None): else: conf = Config() base = ['protocols', 'bfd'] - bfd = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + bfd = conf.get_config_dict(base, get_first_key=True) # Bail out early if configuration tree does not exist if not conf.exists(base): return bfd + # We have gathered the dict representation of the CLI, but there are + # default options which we need to update into the dictionary retrived. + # XXX: T2665: we currently have no nice way for defaults under tag + # nodes, thus we load the defaults "by hand" + default_values = defaults(base + ['peer']) if 'peer' in bfd: - # We have gathered the dict representation of the CLI, but there are - # default options which we need to update into the dictionary retrived. - # XXX: T2665: we currently have no nice way for defaults under tag - # nodes, thus we load the defaults "by hand" - default_values = defaults(base + ['peer']) for peer in bfd['peer']: bfd['peer'][peer] = dict_merge(default_values, bfd['peer'][peer]) + if 'profile' in bfd: + for profile in bfd['profile']: + bfd['profile'][profile] = dict_merge(default_values, bfd['profile'][profile]) + return bfd def verify(bfd): - if not bfd or 'peer' not in bfd: + if not bfd: return None - for peer, peer_config in bfd['peer'].items(): - # IPv6 link local peers require an explicit local address/interface - if is_ipv6_link_local(peer): - if 'source' not in peer_config or len(peer_config['source'] < 2): - raise ConfigError('BFD IPv6 link-local peers require explicit local address and interface setting') - - # IPv6 peers require an explicit local address - if is_ipv6(peer): - if 'source' not in peer_config or 'address' not in peer_config['source']: - raise ConfigError('BFD IPv6 peers require explicit local address setting') - - if 'multihop' in peer_config: - # multihop require source address - if 'source' not in peer_config or 'address' not in peer_config['source']: - raise ConfigError('BFD multihop require source address') - - # multihop and echo-mode cannot be used together - if 'echo_mode' in peer_config: - raise ConfigError('Multihop and echo-mode cannot be used together') - - # multihop doesn't accept interface names - if 'source' in peer_config and 'interface' in peer_config['source']: - raise ConfigError('Multihop and source interface cannot be used together') - - # echo interval can be configured only with enabled echo-mode - if 'interval' in peer_config and 'echo_interval' in peer_config['interval'] and 'echo_mode' not in peer_config: - raise ConfigError('echo-interval can be configured only with enabled echo-mode') + if 'peer' in bfd: + for peer, peer_config in bfd['peer'].items(): + # IPv6 link local peers require an explicit local address/interface + if is_ipv6_link_local(peer): + if 'source' not in peer_config or len(peer_config['source'] < 2): + raise ConfigError('BFD IPv6 link-local peers require explicit local address and interface setting') + + # IPv6 peers require an explicit local address + if is_ipv6(peer): + if 'source' not in peer_config or 'address' not in peer_config['source']: + raise ConfigError('BFD IPv6 peers require explicit local address setting') + + if 'multihop' in peer_config: + # multihop require source address + if 'source' not in peer_config or 'address' not in peer_config['source']: + raise ConfigError('BFD multihop require source address') + + # multihop and echo-mode cannot be used together + if 'echo_mode' in peer_config: + raise ConfigError('Multihop and echo-mode cannot be used together') + + # multihop doesn't accept interface names + if 'source' in peer_config and 'interface' in peer_config['source']: + raise ConfigError('Multihop and source interface cannot be used together') return None @@ -98,7 +99,7 @@ def apply(bfd): # Save original configuration prior to starting any commit actions frr_cfg = frr.FRRConfig() frr_cfg.load_configuration() - frr_cfg.modify_section('bfd', '') + frr_cfg.modify_section('^bfd', '') frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', bfd['new_frr_config']) frr_cfg.commit_configuration() -- cgit v1.2.3 From e9f581efe834dc27e78acff4a331fb9242440de5 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 15 Feb 2021 20:22:17 +0100 Subject: bgp: T1513: add per VRF vni support --- data/templates/frr/vrf.frr.tmpl | 3 +++ interface-definitions/include/vni.xml.i | 12 ++++++++++++ interface-definitions/interfaces-geneve.xml.in | 13 +------------ interface-definitions/interfaces-vxlan.xml.in | 13 +------------ interface-definitions/protocols-vrf.xml.in | 1 + 5 files changed, 18 insertions(+), 24 deletions(-) create mode 100644 interface-definitions/include/vni.xml.i (limited to 'data/templates/frr') diff --git a/data/templates/frr/vrf.frr.tmpl b/data/templates/frr/vrf.frr.tmpl index 0c8726908..8d3d8e9dd 100644 --- a/data/templates/frr/vrf.frr.tmpl +++ b/data/templates/frr/vrf.frr.tmpl @@ -3,6 +3,9 @@ {% if vrf is defined and vrf is not none %} {% for vrf_name, vrf_config in vrf.items() %} vrf {{ vrf_name }} +{% if vrf_config.vni is defined and vrf_config.vni is not none %} + vni {{ vrf_config.vni }} +{% endif %} {% if vrf_config.static is defined and vrf_config.static is not none %} {# IPv4 routes #} {% if vrf_config.static.route is defined and vrf_config.static.route is not none %} diff --git a/interface-definitions/include/vni.xml.i b/interface-definitions/include/vni.xml.i new file mode 100644 index 000000000..faff4c3c3 --- /dev/null +++ b/interface-definitions/include/vni.xml.i @@ -0,0 +1,12 @@ + + + Virtual Network Identifier + + 0-16777214 + VXLAN virtual network identifier + + + + + + diff --git a/interface-definitions/interfaces-geneve.xml.in b/interface-definitions/interfaces-geneve.xml.in index 0c776e3c3..1064b2c18 100644 --- a/interface-definitions/interfaces-geneve.xml.in +++ b/interface-definitions/interfaces-geneve.xml.in @@ -35,18 +35,7 @@ - - - Virtual Network Identifier - - 0-16777214 - GENEVE virtual network identifier - - - - - - + #include diff --git a/interface-definitions/interfaces-vxlan.xml.in b/interface-definitions/interfaces-vxlan.xml.in index f90a86274..234770971 100644 --- a/interface-definitions/interfaces-vxlan.xml.in +++ b/interface-definitions/interfaces-vxlan.xml.in @@ -73,18 +73,7 @@ 8472 - - - Virtual Network Identifier - - 0-16777214 - VXLAN virtual network identifier - - - - - - + #include diff --git a/interface-definitions/protocols-vrf.xml.in b/interface-definitions/protocols-vrf.xml.in index 81942d124..77297938b 100644 --- a/interface-definitions/protocols-vrf.xml.in +++ b/interface-definitions/protocols-vrf.xml.in @@ -27,6 +27,7 @@ #include + #include -- cgit v1.2.3 From 050f44ef1fba3cc23934a65df59ab3d1181cb5d0 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 16 Feb 2021 18:58:21 +0100 Subject: ospfv3: T3313: move interface related options to "protocols ospfv3 interface" --- data/templates/frr/ospfv3.frr.tmpl | 43 ++++++++ interface-definitions/protocols-ospfv3.xml.in | 130 ++++++++++++++----------- smoketest/scripts/cli/test_protocols_ospfv3.py | 63 ++++++++++-- src/conf_mode/protocols_ospf.py | 2 +- src/conf_mode/protocols_ospfv3.py | 12 ++- 5 files changed, 181 insertions(+), 69 deletions(-) (limited to 'data/templates/frr') diff --git a/data/templates/frr/ospfv3.frr.tmpl b/data/templates/frr/ospfv3.frr.tmpl index c63ef80dc..d08972a80 100644 --- a/data/templates/frr/ospfv3.frr.tmpl +++ b/data/templates/frr/ospfv3.frr.tmpl @@ -1,4 +1,47 @@ ! +{% if interface is defined and interface is not none %} +{% for iface, iface_config in interface.items() %} +interface {{ iface }} +{% if iface_config.cost is defined and iface_config.cost is not none %} + ipv6 ospf6 cost {{ iface_config.cost }} +{% endif %} +{% if iface_config.priority is defined and iface_config.priority is not none %} + ipv6 ospf6 priority {{ iface_config.priority }} +{% endif %} +{% if iface_config.hello_interval is defined and iface_config.hello_interval is not none %} + ipv6 ospf6 hello-interval {{ iface_config.hello_interval }} +{% endif %} +{% if iface_config.retransmit_interval is defined and iface_config.retransmit_interval is not none %} + ipv6 ospf6 retransmit-interval {{ iface_config.retransmit_interval }} +{% endif %} +{% if iface_config.transmit_delay is defined and iface_config.transmit_delay is not none %} + ipv6 ospf6 transmit-delay {{ iface_config.transmit_delay }} +{% endif %} +{% if iface_config.dead_interval is defined and iface_config.dead_interval is not none %} + ipv6 ospf6 dead-interval {{ iface_config.dead_interval }} +{% endif %} +{% if iface_config.bfd is defined %} + ipv6 ospf6 bfd +{% endif %} +{% if iface_config.mtu_ignore is defined %} + ipv6 ospf6 mtu-ignore +{% endif %} +{% if iface_config.ifmtu is defined and iface_config.ifmtu is not none %} + ipv6 ospf6 ifmtu {{ iface_config.ifmtu }} +{% endif %} +{% if iface_config.network is defined and iface_config.network is not none %} + ipv6 ospf6 network {{ iface_config.network }} +{% endif %} +{% if iface_config.instance_id is defined and iface_config.instance_id is not none %} + ipv6 ospf6 instance-id {{ iface_config.instance_id }} +{% endif %} +{% if iface_config.passive is defined %} + ipv6 ospf6 passive +{% endif %} +! +{% endfor %} +{% endif %} +! router ospf6 {% if area is defined and area is not none %} {% for area_id, area_config in area.items() %} diff --git a/interface-definitions/protocols-ospfv3.xml.in b/interface-definitions/protocols-ospfv3.xml.in index e28faa3cf..2559e2b03 100644 --- a/interface-definitions/protocols-ospfv3.xml.in +++ b/interface-definitions/protocols-ospfv3.xml.in @@ -41,7 +41,7 @@ - + Enable routing on an IPv6 interface @@ -54,63 +54,9 @@ + - - #include - #include - - - Interface MTU - - u32:1-65535 - Interface MTU - - - - - - - - - Instance Id (default: 0) - - u32:0-255 - Instance Id - - - - - - 0 - - - - Network type - - broadcast point-to-point - - - broadcast - Broadcast network type - - - point-to-point - Point-to-point network type - - - ^(broadcast|point-to-point)$ - - Must be broadcast or point-to-point - - - - - Disable forming of adjacency - - - - - + Specify IPv6 prefix (border routers only) @@ -201,6 +147,76 @@ + + + Enable routing on an IPv6 interface + + + + + txt + Interface used for routing information exchange + + + + + + + #include + #include + + + Interface MTU + + u32:1-65535 + Interface MTU + + + + + + + + + Instance Id (default: 0) + + u32:0-255 + Instance Id + + + + + + 0 + + + + Network type + + broadcast point-to-point + + + broadcast + Broadcast network type + + + point-to-point + Point-to-point network type + + + ^(broadcast|point-to-point)$ + + Must be broadcast or point-to-point + + + + + Disable forming of adjacency + + + + + OSPFv3 specific parameters diff --git a/smoketest/scripts/cli/test_protocols_ospfv3.py b/smoketest/scripts/cli/test_protocols_ospfv3.py index 297d5d996..754c4488f 100755 --- a/smoketest/scripts/cli/test_protocols_ospfv3.py +++ b/smoketest/scripts/cli/test_protocols_ospfv3.py @@ -25,10 +25,15 @@ from vyos.util import process_named_running PROCESS_NAME = 'ospf6d' base_path = ['protocols', 'ospfv3'] +router_id = '192.0.2.1' +default_area = '0' def getFRROSPFconfig(): return cmd('vtysh -c "show run" | sed -n "/router ospf6/,/^!/p"') +def getFRRIFconfig(iface): + return cmd(f'vtysh -c "show run" | sed -n "/^interface {iface}/,/^!/p"') + class TestProtocolsOSPFv3(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) @@ -43,23 +48,21 @@ class TestProtocolsOSPFv3(unittest.TestCase): def test_ospfv3_01_basic(self): - area = '0' seq = '10' prefix = '2001:db8::/32' acl_name = 'foo-acl-100' - router_id = '192.0.2.1' self.session.set(['policy', 'access-list6', acl_name, 'rule', seq, 'action', 'permit']) self.session.set(['policy', 'access-list6', acl_name, 'rule', seq, 'source', 'any']) self.session.set(base_path + ['parameters', 'router-id', router_id]) - self.session.set(base_path + ['area', area, 'range', prefix, 'advertise']) - self.session.set(base_path + ['area', area, 'export-list', acl_name]) - self.session.set(base_path + ['area', area, 'import-list', acl_name]) + self.session.set(base_path + ['area', default_area, 'range', prefix, 'advertise']) + self.session.set(base_path + ['area', default_area, 'export-list', acl_name]) + self.session.set(base_path + ['area', default_area, 'import-list', acl_name]) interfaces = Section.interfaces('ethernet') for interface in interfaces: - self.session.set(base_path + ['area', area, 'interface', interface]) + self.session.set(base_path + ['area', default_area, 'interface', interface]) # commit changes self.session.commit() @@ -67,13 +70,13 @@ class TestProtocolsOSPFv3(unittest.TestCase): # Verify FRR ospfd configuration frrconfig = getFRROSPFconfig() self.assertIn(f'router ospf6', frrconfig) - self.assertIn(f' area {area} range {prefix}', frrconfig) + self.assertIn(f' area {default_area} range {prefix}', frrconfig) self.assertIn(f' ospf6 router-id {router_id}', frrconfig) - self.assertIn(f' area {area} import-list {acl_name}', frrconfig) - self.assertIn(f' area {area} export-list {acl_name}', frrconfig) + self.assertIn(f' area {default_area} import-list {acl_name}', frrconfig) + self.assertIn(f' area {default_area} export-list {acl_name}', frrconfig) for interface in interfaces: - self.assertIn(f' interface {interface} area {area}', frrconfig) + self.assertIn(f' interface {interface} area {default_area}', frrconfig) self.session.delete(['policy', 'access-list6', acl_name]) @@ -118,6 +121,46 @@ class TestProtocolsOSPFv3(unittest.TestCase): for protocol in redistribute: self.assertIn(f' redistribute {protocol} route-map {route_map}', frrconfig) + def test_ospfv3_0104_interfaces(self): + + self.session.set(base_path + ['parameters', 'router-id', router_id]) + self.session.set(base_path + ['area', default_area]) + + cost = '100' + priority = '10' + interfaces = Section.interfaces('ethernet') + for interface in interfaces: + if_base = base_path + ['interface', interface] + self.session.set(if_base + ['bfd']) + self.session.set(if_base + ['cost', cost]) + self.session.set(if_base + ['instance-id', '0']) + self.session.set(if_base + ['mtu-ignore']) + self.session.set(if_base + ['network', 'point-to-point']) + self.session.set(if_base + ['passive']) + self.session.set(if_base + ['priority', priority]) + cost = str(int(cost) + 10) + priority = str(int(priority) + 5) + + # commit changes + self.session.commit() + + # Verify FRR ospfd configuration + frrconfig = getFRROSPFconfig() + self.assertIn(f'router ospf6', frrconfig) + + cost = '100' + priority = '10' + for interface in interfaces: + if_config = getFRRIFconfig(interface) + self.assertIn(f'interface {interface}', if_config) + self.assertIn(f' ipv6 ospf6 bfd', if_config) + self.assertIn(f' ipv6 ospf6 cost {cost}', if_config) + self.assertIn(f' ipv6 ospf6 mtu-ignore', if_config) + self.assertIn(f' ipv6 ospf6 network point-to-point', if_config) + self.assertIn(f' ipv6 ospf6 passive', if_config) + self.assertIn(f' ipv6 ospf6 priority {priority}', if_config) + cost = str(int(cost) + 10) + priority = str(int(priority) + 5) if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/src/conf_mode/protocols_ospf.py b/src/conf_mode/protocols_ospf.py index 2ce0ab530..6d9eb828b 100755 --- a/src/conf_mode/protocols_ospf.py +++ b/src/conf_mode/protocols_ospf.py @@ -137,7 +137,7 @@ def apply(ospf): # Save original configuration prior to starting any commit actions frr_cfg = frr.FRRConfig() frr_cfg.load_configuration(frr_daemon) - frr_cfg.modify_section(r'interface \S+', '') + frr_cfg.modify_section(r'^interface \S+', '') frr_cfg.modify_section('^router ospf$', '') frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', ospf['new_frr_config']) frr_cfg.commit_configuration(frr_daemon) diff --git a/src/conf_mode/protocols_ospfv3.py b/src/conf_mode/protocols_ospfv3.py index 6c3aaf426..6f068b196 100755 --- a/src/conf_mode/protocols_ospfv3.py +++ b/src/conf_mode/protocols_ospfv3.py @@ -23,6 +23,7 @@ from vyos.configdict import dict_merge from vyos.configverify import verify_route_maps from vyos.template import render_to_string from vyos.util import call +from vyos.ifconfig import Interface from vyos.xml import defaults from vyos import ConfigError from vyos import frr @@ -57,6 +58,14 @@ def verify(ospfv3): return None verify_route_maps(ospfv3) + + if 'interface' in ospfv3: + for ifname, if_config in ospfv3['interface'].items(): + if 'ifmtu' in if_config: + mtu = Interface(ifname).get_mtu() + if int(if_config['ifmtu']) > int(mtu): + raise ConfigError(f'OSPFv3 ifmtu cannot go beyond physical MTU of "{mtu}"') + return None def generate(ospfv3): @@ -71,7 +80,8 @@ def apply(ospfv3): # Save original configuration prior to starting any commit actions frr_cfg = frr.FRRConfig() frr_cfg.load_configuration(frr_daemon) - frr_cfg.modify_section('router ospf6', '') + frr_cfg.modify_section(r'^interface \S+', '') + frr_cfg.modify_section('^router ospf6$', '') frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', ospfv3['new_frr_config']) frr_cfg.commit_configuration(frr_daemon) -- cgit v1.2.3 From 7f2b376cb07c2a0407daf2677defddc880ca907f Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 16 Feb 2021 19:04:48 +0100 Subject: bgp: T2100: always set "no bgp network import-check" In order to keep the current behavior when upgrading from 1.2 -> 1.3 -> 1.4 FRR requires us to set this option. This configuration modifies the behavior of the network statement. If you have this configured the underlying network must exist in the rib (default). If you have the [no] form configured then BGP will not check for the networks existence in the rib. For FRR versions 7.3 and before frr defaults for datacenter were the network must exist, traditional did not check for existence. For versions 7.4 and beyond both traditional and datacenter the network must exist. VyOS uses "traditional". --- data/templates/frr/bgp.frr.tmpl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'data/templates/frr') diff --git a/data/templates/frr/bgp.frr.tmpl b/data/templates/frr/bgp.frr.tmpl index bb8131730..4cb2ad092 100644 --- a/data/templates/frr/bgp.frr.tmpl +++ b/data/templates/frr/bgp.frr.tmpl @@ -176,8 +176,10 @@ ! router bgp {{ asn }} {# Disable eBGP policy by default until there is a CLI option #} -{# https://phabricator.vyos.net/T3183 & https://phabricator.vyos.net/T2100 #} +{# Workaround for T3183 until we have decided about a migration script #} no bgp ebgp-requires-policy +{# 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() %} ! -- cgit v1.2.3 From 0fb5cc02c6c16ef410c1b1f746c1fbfbc40a0da0 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 16 Feb 2021 19:14:35 +0100 Subject: ospf: T3047: support virtual-link interfaces on "passive-interface-exclude" This superseeds GitHub pull request #723 by implementing support to add an OSPF virtual-link interface which connects different areas to the "no passive-interface" configuration option when the system uses "passive-interface default". Setting "protocols ospf passive-interface-exclude vlink0" on the VyOS CLI will render the FRR OSPF configuration "no passive-interface VLINK0". --- data/templates/frr/ospf.frr.tmpl | 3 +++ interface-definitions/protocols-ospf.xml.in | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'data/templates/frr') diff --git a/data/templates/frr/ospf.frr.tmpl b/data/templates/frr/ospf.frr.tmpl index 7ca69eee6..140b6b406 100644 --- a/data/templates/frr/ospf.frr.tmpl +++ b/data/templates/frr/ospf.frr.tmpl @@ -159,6 +159,9 @@ router ospf passive-interface {{ interface }} {% endfor %} {% for interface in passive_interface_exclude if passive_interface_exclude is defined %} +{% if interface.startswith('vlink') %} +{% set interface = interface.upper() %} +{% endif %} no passive-interface {{ interface }} {% endfor %} {% if redistribute is defined and redistribute is not none %} diff --git a/interface-definitions/protocols-ospf.xml.in b/interface-definitions/protocols-ospf.xml.in index d0cfa14b1..4c480c71d 100644 --- a/interface-definitions/protocols-ospf.xml.in +++ b/interface-definitions/protocols-ospf.xml.in @@ -661,10 +661,15 @@ txt - Interface to be passive (i.e. suppress routing updates) + Interface to exclude when suppressing routing updates + + + vlinkN + Virtual-link interface to exclude when suppressing routing updates + ^(vlink[0-9]+)$ -- cgit v1.2.3 From 79ebf56dd18d62b5ff0ed8efadbc92bca2ebfffd Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 16 Feb 2021 22:01:19 +0100 Subject: bfd: T3310: use end to exit FRR scope We need to exit from the bfd context by end instead of exit, else FRR reload will get confused: frr-reload output: 168 2021-02-16 21:13:19,014 DEBUG: LINE ip prefix-list GLOBAL seq 10 permit 192.168.100.1/32: append to current_context_lines, ['bfd'] --- data/templates/frr/bfd.frr.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'data/templates/frr') diff --git a/data/templates/frr/bfd.frr.tmpl b/data/templates/frr/bfd.frr.tmpl index 3b3d13f9d..16f8be92c 100644 --- a/data/templates/frr/bfd.frr.tmpl +++ b/data/templates/frr/bfd.frr.tmpl @@ -40,5 +40,5 @@ bfd exit {% endfor %} {% endif %} - exit + end ! -- cgit v1.2.3 From b5f67d4ea18dce4d9d5586d5a11590c6a45b3251 Mon Sep 17 00:00:00 2001 From: sever-sever Date: Fri, 19 Feb 2021 11:48:38 +0000 Subject: bgp: T3330: Fix capability orf prefix-list --- data/templates/frr/bgp.frr.tmpl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'data/templates/frr') diff --git a/data/templates/frr/bgp.frr.tmpl b/data/templates/frr/bgp.frr.tmpl index 4cb2ad092..08b6cb791 100644 --- a/data/templates/frr/bgp.frr.tmpl +++ b/data/templates/frr/bgp.frr.tmpl @@ -108,8 +108,11 @@ {% 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 is not none %} - neighbor {{ neighbor }} capability orf prefix-list {{ afi_config.capability.orf.prefix_list }} +{% 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 }} -- cgit v1.2.3 From b5763e329915435b411e360243839cb7817ff055 Mon Sep 17 00:00:00 2001 From: sever-sever Date: Fri, 19 Feb 2021 15:04:40 +0000 Subject: bgp: T3322: Fix timers for neighbor --- data/templates/frr/bgp.frr.tmpl | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'data/templates/frr') diff --git a/data/templates/frr/bgp.frr.tmpl b/data/templates/frr/bgp.frr.tmpl index 4cb2ad092..6ba223196 100644 --- a/data/templates/frr/bgp.frr.tmpl +++ b/data/templates/frr/bgp.frr.tmpl @@ -58,6 +58,14 @@ {% 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 %} -- cgit v1.2.3