diff --git a/plugins/action/common/prepare_plugins/prep_108_vrf_lites.py b/plugins/action/common/prepare_plugins/prep_108_vrf_lites.py index 71f8290e5..7bb152903 100644 --- a/plugins/action/common/prepare_plugins/prep_108_vrf_lites.py +++ b/plugins/action/common/prepare_plugins/prep_108_vrf_lites.py @@ -56,10 +56,16 @@ def prepare(self): for vrf_lite in model_data["vxlan"]["overlay_extensions"]["vrf_lites"]: ospf_enabled = True if vrf_lite.get( "ospf") is not None else False - default_area = vrf_lite.get("ospf", {}).get( + default_ospf_area = vrf_lite.get("ospf", {}).get( "default_area", default_values["vxlan"]["overlay_extensions"]["vrf_lites"]["ospf"]["default_area"] ) + ospfv3_enabled = True if vrf_lite.get( + "ospfv3") is not None else False + default_ospfv3_area = vrf_lite.get("ospfv3", {}).get( + "default_area", + default_values["vxlan"]["overlay_extensions"]["vrf_lites"]["ospfv3"]["default_area"] + ) for switch in vrf_lite["switches"]: unique_name = f"{vrf_lite['name']}_{switch['name']}" @@ -151,10 +157,22 @@ def prepare(self): continue if intf.get("ospf") is None: intf["ospf"] = { - "area": default_area + "area": default_ospf_area + } + else: + intf["ospf"]["area"] = default_ospf_area + switch["interfaces"][intf_index] = intf + + for intf_index in range(len(switch.get("interfaces", []))): + intf = switch["interfaces"][intf_index] + if not ospfv3_enabled or (intf.get("ospfv3") is not None and intf["ospfv3"].get("area", -1) != -1): + continue + if intf.get("ospfv3") is None: + intf["ospfv3"] = { + "area": default_ospfv3_area } else: - intf["ospf"]["area"] = default_area + intf["ospfv3"]["area"] = default_ospfv3_area switch["interfaces"][intf_index] = intf # Adding address_family_ipv4_unicast and address_family_ipv6_unicast and child keys diff --git a/roles/dtc/common/templates/ndfc_vrf_lite.j2 b/roles/dtc/common/templates/ndfc_vrf_lite.j2 index 5767eb140..ab4f9662c 100644 --- a/roles/dtc/common/templates/ndfc_vrf_lite.j2 +++ b/roles/dtc/common/templates/ndfc_vrf_lite.j2 @@ -1,6 +1,9 @@ {% if item.ospf is defined and item.ospf %} {% include 'ndfc_vrf_lite/ndfc_vrf_lite_ospf.j2' %} {% endif %} +{% if item.ospfv3 is defined and item.ospfv3 %} + {% include 'ndfc_vrf_lite/ndfc_vrf_lite_ospfv3.j2' %} +{% endif %} {% if (item.bgp is defined and item.bgp) or switch_item.bgp_peers or switch_item.bgp %} {% include 'ndfc_vrf_lite/ndfc_vrf_lite_ebgp.j2' %} {% endif %} diff --git a/roles/dtc/common/templates/ndfc_vrf_lite/ndfc_vrf_lite_ebgp.j2 b/roles/dtc/common/templates/ndfc_vrf_lite/ndfc_vrf_lite_ebgp.j2 index da0b14313..049661e18 100644 --- a/roles/dtc/common/templates/ndfc_vrf_lite/ndfc_vrf_lite_ebgp.j2 +++ b/roles/dtc/common/templates/ndfc_vrf_lite/ndfc_vrf_lite_ebgp.j2 @@ -77,8 +77,8 @@ {% if switch_redist.source == 'static' and switch_redist.route_map_ipv6 %} redistribute static route-map {{ switch_redist.route_map_ipv6 }} {% endif %} - {% if switch_redist.source == 'ospf' and switch_redist.route_map_ipv6 %} - redistribute ospf {{ switch_redist.protocol_tag }} route-map {{ switch_redist.route_map_ipv6 }} + {% if switch_redist.source == 'ospfv3' and switch_redist.route_map_ipv6 and switch_redist.protocol_tag %} + redistribute ospfv3 {{ switch_redist.protocol_tag }} route-map {{ switch_redist.route_map_ipv6 }} {% endif %} {% endfor %} {% endif %} diff --git a/roles/dtc/common/templates/ndfc_vrf_lite/ndfc_vrf_lite_ospfv3.j2 b/roles/dtc/common/templates/ndfc_vrf_lite/ndfc_vrf_lite_ospfv3.j2 new file mode 100644 index 000000000..d7bfd709a --- /dev/null +++ b/roles/dtc/common/templates/ndfc_vrf_lite/ndfc_vrf_lite_ospfv3.j2 @@ -0,0 +1,302 @@ +! This NDFC VRF-Lite OSPFv3 config data structure is auto-generated +! DO NOT EDIT MANUALLY +! +! +{% set simplified_fabric_type = MD_Extended.vxlan.fabric.simplified_type %} +{%- set areas_default_information_originate = [] -%} +{# macro render_ospf_interface to render ospf area part #} +{% macro render_ospf_area(area, defaults) %} + {% if area.id and (area.id != 0 or area.id != '0.0.0.0') %} + {% if (area.area_type and area.area_type == 'stub') or (area.area_type is not defined and defaults.vxlan.overlay_extensions.vrf_lites.ospfv3.areas.area_type == 'stub') %} + area {{ area.id | ipaddr('address') }} stub + {% elif (area.area_type and area.area_type == 'totally_stub') or (area.area_type is not defined and defaults.vxlan.overlay_extensions.vrf_lites.ospfv3.areas.area_type == 'totally_stub') %} + area {{ area.id | ipaddr('address') }} stub no-summary + {% elif (area.area_type and area.area_type == 'nssa') or (area.area_type is not defined and defaults.vxlan.overlay_extensions.vrf_lites.ospfv3.areas.area_type == 'nssa') %} + {% if area.nssa is not defined %} + area {{ area.id | ipaddr('address') }} nssa + {% else %} + {%- set nssa_options = { + 'no_redistribution': area.nssa.no_redistribution | default(defaults.vxlan.overlay_extensions.vrf_lites.ospfv3.nssa.no_redistribution), + 'no_summary': area.nssa.no_summary | default(defaults.vxlan.overlay_extensions.vrf_lites.ospfv3.nssa.no_summary), + 'default_information_originate': area.nssa.default_information_originate | default(defaults.vxlan.overlay_extensions.vrf_lites.ospfv3.nssa.default_information_originate), + 'translate_always': area.nssa.translate.always | default(defaults.vxlan.overlay_extensions.vrf_lites.ospfv3.nssa.translate.always), + 'translate_supress_fa': area.nssa.translate.supress_fa | default(defaults.vxlan.overlay_extensions.vrf_lites.ospfv3.nssa.translate.supress_fa), + 'translate_never': area.nssa.translate.never | default(defaults.vxlan.overlay_extensions.vrf_lites.ospfv3.nssa.translate.never) + } -%} + {%- set nssa_options_flags = [] -%} + {%- set nssa_options_translate = [] -%} + {%- set nssa_options_flags_enabled = false -%} + {%- set nssa_options_translate_enabled = false -%} + {% if nssa_options.no_summary is true %} + {%- set _= nssa_options_flags.append("no-summary") -%} + {%- set nssa_options_flags_enabled = true -%} + {% endif %} + {% if nssa_options.no_redistribution is true %} + {% set _= nssa_options_flags.append("no-redistribution") -%} + {%- set nssa_options_flags_enabled = true -%} + {% endif %} + {% if nssa_options.default_information_originate is true %} + {% set _= nssa_options_flags.append("default-information-originate") %} + {% if area.nssa.route_map %} + {% set _= nssa_options_flags.append("route-map") %} + {% set _= nssa_options_flags.append(area.nssa.route_map) %} + {% set nssa_options_flags_enabled = true %} + {% endif %} + {% endif %} + {% if nssa_options.translate_always is true %} + {% set _= nssa_options_translate.append("always") %} + {% set nssa_options_translate_enabled = true %} + {% endif %} + {% if nssa_options.translate_supress_fa is true %} + {% set _= nssa_options_translate.append("supress-fa") %} + {% set nssa_options_translate_enabled = true %} + {% endif %} + {% if nssa_options.translate_never is true %} + {% set _= nssa_options_translate.append("never") %} + {% set nssa_options_translate_enabled = true %} + {% endif %} + {% if nssa_options_flags_enabled is true %} + area {{ area.id | ipaddr('address') }} nssa {{ nssa_options_flags | join(' ') }} + {% endif %} + {% if nssa_options_translate_enabled is true %} + area {{ area.id | ipaddr('address') }} nssa translate type7 {{ nssa_options_translate | join(' ') }} + {% endif %} + {% endif %} + {% endif %} + {% endif %} + {% if area.area_cost is defined and area.area_cost != 1 and area.id != 0 %} + area {{ area.id | ipaddr('address') }} default-cost {{ area.area_cost }} + {% elif area.area_cost is defined and area.area_cost != 1 %} + area 0.0.0.0 default-cost {{ area.area_cost }} + {% endif %} + {% if area.default_information_originate is defined %} + {% if area.default_information_originate.always is not defined %} + {% set default_information_originate_always = defaults.vxlan.overlay_extensions.vrf_lites.ospfv3.default_information_originate.always %} + {% else %} + {% set default_information_originate_always = area.default_information_originate.always %} + {% endif %} + {% if (default_information_originate_always is true and area.default_information_originate.route_map is defined) %} + {# default-information originate always route-map {{ area.default_information_originate.route_map }} #} + {%- set _= areas_default_information_originate.append('default-information originate always route-map ' ~ area.default_information_originate.route_map) -%} + {% elif default_information_originate_always is true and area.default_information_originate.route_map is not defined %} + {# default-information originate always #} + {%- set _= areas_default_information_originate.append('default-information originate always') -%} + {% elif default_information_originate_always is false and area.default_information_originate.route_map is defined %} + {# default-information originate route-map {{ area.default_information_originate.route_map }} #} + {%- set _= areas_default_information_originate.append('default-information originate route-map ' ~ area.default_information_originate.route_map) -%} + {% else %} + {# default-information originate #} + {%- set _= areas_default_information_originate.append('default-information originate') -%} + {% endif %} + {% endif %} +{% endmacro %} + +feature ospfv3 +{% set redistribute = {} %} +{% set feature = {} %} +{% if item.ospfv3.bfd.enabled | default(defaults.vxlan.overlay_extensions.vrf_lites.ospfv3.bfd.enabled) %} + {% set _ = feature.update({'bfd': true}) %} +{% endif %} +{% if switch_item.interfaces %} + {% for interface in switch_item.interfaces %} + {% if interface.ospfv3.bfd.enabled | default(defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.bfd.enabled) %} + {% set _ = feature.update({'bfd': true}) %} + {% endif %} + {% if interface.ospfv3.authentication.auth_type != 'none' | default(defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.authentication.auth_type != 'none' )%} + {% set _ = feature.update({'imp': true}) %} + {% endif %} + {% endfor %} +{% endif %} +{% if feature['bfd']%} +feature bfd +! +{% endif %} +{% if feature['imp']%} +feature imp +! +{% endif %} +! +router ospfv3 {{ item.ospfv3['process'] }} +{# GRT #} +{% if item.vrf.lower() == "default" %} +{% if item.ospfv3.areas is defined and item.ospfv3.areas %} +{% for area in item.ospfv3.areas %} + {% if area.authentication['auth_type'] != 'none' and area.authentication['auth_key'] %} + {% set spi = area.authentication['security_parameter_index'] | default(defaults.vxlan.overlay_extensions.vrf_lites.ospfv3.areas.authentication.security_parameter_index) %} + {% if area.id is defined %} + {% set area_id = '' %} + {% if area.id == 0 or area.id == '0.0.0.0' %} + {% set area_id = '0.0.0.0' %} + {% else %} + {% set area_id = area.id | ipaddr('address') %} + {% endif %} + area {{ area_id }} authentication ipsec spi {{ spi }} {{ area.authentication['auth_type'] }} 3 {{ area.authentication['auth_key'] }} + {% endif %} + {% endif %} +{% endfor %} +{% endif %} +{% if item.ospfv3.authentication['auth_type'] != 'none' and item.ospfv3.authentication['auth_key'] %} + {% set spi = item.ospfv3.authentication['security_parameter_index'] | default(defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.authentication.security_parameter_index) %} + authentication ipsec spi {{ spi }} {{ item.ospfv3.authentication['auth_type'] }} 3 {{ item.ospfv3.authentication['auth_key'] }} +{% endif %} +{% if switch_item['router_id'] %} + router-id {{ switch_item['router_id'] }} +{% endif %} +{% if item.ospfv3.areas is defined and item.ospfv3.areas %} +{% for area in item.ospfv3.areas %} + {{- render_ospf_area(area, defaults) -}} +{% endfor %} +{% endif %} + address-family ipv6 unicast + {% for item in areas_default_information_originate %} + {{ item }} + {% endfor %} + {%- set areas_default_information_originate = [] -%} + {% if (item.ospfv3.distance and item.ospfv3.distance != 110) or (item.ospfv3.distance is not defined and defaults.vxlan.overlay_extensions.vrf_lites.ospfv3.distance != 110) %} + distance {{ item.ospfv3.distance }} + {% endif %} + {# Redistribution configuration #} + {% if switch_item.redistribution %} + {% for switch_redist in switch_item.redistribution %} + {% if switch_redist.source == 'direct' and switch_redist.route_map_ipv6 %} + redistribute direct route-map {{ switch_redist.route_map_ipv6 }} + {% endif %} + {% if switch_redist.source == 'static' and switch_redist.route_map_ipv6 %} + redistribute static route-map {{ switch_redist.route_map_ipv6 }} + {% endif %} + {% if switch_redist.source == 'bgp' and switch_redist.route_map_ipv6 %} + redistribute bgp {{ MD_Extended.vxlan.global[simplified_fabric_type].bgp_asn }} route-map {{ switch_redist.route_map_ipv6 }} + {% endif %} + {% if switch_redist.source == 'ospfv3' and switch_redist.route_map_ipv6 %} + {% set _ = redistribute.update({'ospfv3': switch_redist.route_map_ipv6}) %} + {% endif %} + {% endfor %} + {% endif %} +{% else %} +{# Other vrfs #} + vrf {{ item.vrf }} + {% if item.ospfv3.areas is defined and item.ospfv3.areas %} + {% for area in item.ospfv3.areas %} + {% if area.authentication['auth_type'] != 'none' and area.authentication['auth_key'] %} + {% set spi = area.authentication['security_parameter_index'] | default(defaults.vxlan.overlay_extensions.vrf_lites.ospfv3.areas.authentication.security_parameter_index) %} + {% set area_id = '' %} + {% if area.id is defined %} + {% if area.id == 0 or area.id == '0.0.0.0' %} + {% set area_id = '0.0.0.0' %} + {% else %} + {% set area_id = area.id | ipaddr('address') %} + {% endif %} + area {{ area_id }} authentication ipsec spi {{ spi }} {{ area.authentication['auth_type'] }} 3 {{ area.authentication['auth_key'] }} + {% endif %} + {% endif %} + {% endfor %} + {% endif %} + {% if item.ospfv3.authentication['auth_type'] != 'none' and item.ospfv3.authentication['auth_key'] %} + {% set spi = item.ospfv3.authentication['security_parameter_index'] | default(defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.authentication.security_parameter_index) %} + authentication ipsec spi {{ spi }} {{ item.ospfv3.authentication['auth_type'] }} 3 {{ item.ospfv3.authentication['auth_key'] }} + {% endif %} + {% if switch_item['router_id'] %} + router-id {{ switch_item['router_id'] }} + {% endif %} + {% if item.ospfv3.areas is defined and item.ospfv3.areas %} + {% for area in item.ospfv3.areas %} + {{- render_ospf_area(area, defaults) | indent(2, True) -}} + {% endfor %} + {% endif %} + address-family ipv6 unicast + {% for item in areas_default_information_originate %} + {{ item }} + {% endfor %} + {% if (item.ospfv3.distance and item.ospfv3.distance != 110) or (item.ospfv3.distance is not defined and defaults.vxlan.overlay_extensions.vrf_lites.ospfv3.distance != 110) %} + distance {{ item.ospfv3.distance }} + {% endif %} + {# Redistribution configuration #} + {% if switch_item.redistribution %} + {% for switch_redist in switch_item.redistribution %} + {% if switch_redist.source == 'direct' and switch_redist.route_map_ipv6 %} + redistribute direct route-map {{ switch_redist.route_map_ipv6 }} + {% endif %} + {% if switch_redist.source == 'static' and switch_redist.route_map_ipv6 %} + redistribute static route-map {{ switch_redist.route_map_ipv6 }} + {% endif %} + {% if switch_redist.source == 'bgp' and switch_redist.route_map_ipv6 %} + redistribute bgp {{ MD_Extended.vxlan.global[simplified_fabric_type].bgp_asn }} route-map {{ switch_redist.route_map_ipv6 }} + {% endif %} + {% if switch_redist.source == 'ospfv3' and switch_redist.route_map_ipv6 %} + {% set _ = redistribute.update({'ospfv3': switch_redist.route_map_ipv6}) %} + {% endif %} + {% endfor %} + {% endif %} +{% endif %} +! +{% if simplified_fabric_type == 'ibgp' %} + {% if redistribute['ospfv3'] %} +router bgp {{ MD_Extended.vxlan.global[simplified_fabric_type].bgp_asn }} + {% if item.vrf.lower() != "default" %} + vrf {{ item.vrf }} + address-family ipv6 unicast + redistribute ospfv3 {{ item.ospfv3['process'] }} route-map {{ redistribute['ospfv3'] }} + {% endif %} + {% endif %} +{% endif %} +! +{% if switch_item.interfaces %} + {% for interface in switch_item.interfaces %} + {% set interface_name = interface['name'] | lower %} +interface {{ interface['name'] }} + {% if interface.ospfv3.authentication['auth_type'] != 'none' and interface.ospfv3.authentication['auth_key'] %} + {% set spi = interface.ospfv3.authentication['security_parameter_index'] | default(defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.authentication.security_parameter_index) %} + ospfv3 authentication ipsec spi {{ spi }} {{ interface.ospfv3.authentication['auth_type'] }} 3 {{ interface.ospfv3.authentication['auth_key'] }} + {% endif %} + {% if interface_name.startswith('lo') %} + {% if interface.ospfv3['network_type'] and interface.ospfv3['network_type'] != 'broadcast' %} + ospfv3 network {{ interface.ospf['network_type'] }} + {% endif %} + {% elif interface.ospfv3['network_type'] %} + ospfv3 network {{ interface.ospfv3['network_type'] }} + {% endif %} + {% if interface.ospfv3['area'] is defined and interface.ospfv3['area'] != 0 %} + ipv6 router ospfv3 {{ item.ospfv3['process'] }} area {{ interface.ospfv3['area'] | ipaddr('address') }} + {% else %} + ipv6 router ospfv3 {{ item.ospfv3['process'] }} area 0.0.0.0 + {% endif %} + {% if interface.ospfv3.cost %} + ospfv3 cost {{ interface.ospfv3.cost }} + {% elif defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.cost and defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.cost != 1 %} + ospfv3 cost {{ defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.cost }} + {% endif %} + {% if interface_name.startswith('lo') %} + {% elif interface.ospfv3.passive_interface | default(defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.passive_interface ) %} + ospfv3 passive-interface + {% endif %} + {% if interface.ospfv3.mtu_ignore | default(defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.mtu_ignore) %} + ospfv3 mtu-ignore + {% endif %} + {% if interface.ospfv3.bfd.enabled == false %} + {% elif interface.ospfv3.bfd.enabled or (interface.ospfv3.bfd.enabled is not defined and feature['bfd']) %} + ospfv3 bfd + {% endif %} + {% if interface.ospfv3.hello_interval and interface.ospfv3.hello_interval != 10 %} + ospfv3 hello-interval {{ interface.ospfv3.hello_interval }} + {% elif defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.hello_interval and defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.hello_interval != 10 %} + ospfv3 hello-interval {{ defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.hello_interval }} + {% endif %} + ospfv3 dead-interval {{ interface.ospfv3.dead_interval | default(defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.dead_interval) }} + {% if interface.ospfv3.priority and interface.ospfv3.priority != 1 %} + ospfv3 priority {{ interface.ospfv3.priority }} + {% elif defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.priority and defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.priority != 1 %} + ospfv3 priority {{ defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.priority }} + {% endif %} + {% if interface.ospfv3.lsa_retransmit_interval and interface.ospfv3.lsa_retransmit_interval != 5 %} + ospfv3 retransmit-interval {{ interface.ospfv3.lsa_retransmit_interval }} + {% elif defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.lsa_retransmit_interval and defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.lsa_retransmit_interval != 5 %} + ospfv3 retransmit-interval {{ defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.lsa_retransmit_interval }} + {% endif %} + {% if interface.ospfv3.lsa_transmit_delay and interface.ospfv3.lsa_transmit_delay != 1 %} + ospfv3 transmit-delay {{ interface.ospfv3.lsa_transmit_delay }} + {% elif defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.lsa_transmit_delay and defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.lsa_transmit_delay != 1 %} + ospfv3 transmit-delay {{ defaults.vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospfv3.lsa_transmit_delay }} + {% endif %} +! + {% endfor %} +{% endif %} diff --git a/roles/validate/files/defaults.yml b/roles/validate/files/defaults.yml index 3856e9cd3..82eb27725 100644 --- a/roles/validate/files/defaults.yml +++ b/roles/validate/files/defaults.yml @@ -375,6 +375,29 @@ factory_defaults: always: false supress_fa: false never: false + ospfv3: + areas: + area_type: standard + authentication: + auth_type: none + security_parameter_index: 256 + default_area: 0 + distance: 110 + bfd: + enabled: false + authentication: + auth_type: none + security_parameter_index: 256 + default_information_originate: + always: false + nssa: + default_information_originate: false + no_redistribution: false + no_summary: false + translate: + always: false + supress_fa: false + never: false bgp: best_path_as_path_relax: false graceful_restart: true @@ -410,6 +433,21 @@ factory_defaults: priority: 1 lsa_retransmit_interval: 5 lsa_transmit_delay: 1 + ospfv3: + authentication: + auth_type: none + security_parameter_index: 256 + cost: 1 + passive_interface: false + mtu_ignore: false + bfd: + enabled: false + hello_interval: 10 + dead_interval: 40 + network_type: broadcast + priority: 1 + lsa_retransmit_interval: 5 + lsa_transmit_delay: 1 bgp_peers: next_hop_self: false bfd: diff --git a/roles/validate/files/rules/ibgp_vxlan/502_policy_vrf_lite_cross_reference.py b/roles/validate/files/rules/ibgp_vxlan/502_policy_vrf_lite_cross_reference.py index f89ad55b7..4d1419c36 100644 --- a/roles/validate/files/rules/ibgp_vxlan/502_policy_vrf_lite_cross_reference.py +++ b/roles/validate/files/rules/ibgp_vxlan/502_policy_vrf_lite_cross_reference.py @@ -20,6 +20,8 @@ vxlan.overlay_extensions.vrf_lites.switches.interfaces.ospf.network_type """ +OSPF_VERSIONS = ["ospf", "ospfv3"] + class Rule: """ @@ -88,13 +90,22 @@ def match(cls, data_model): @classmethod def check_global_ospf_and_bgp(cls, policy): """ - Check if OSPF and BGP is enabled in the global policy + Check if OSPF, OSPFv3 or BGP are enabled in the global policy """ - if {"ospf", "bgp"}.issubset(policy): + for ospf_version in OSPF_VERSIONS: + if {ospf_version, "bgp"}.issubset(policy): + cls.results.append( + f"vxlan.overlay_extensions.vrf_lites.{policy['name']}.{ospf_version}, " + f"vxlan.overlay_extensions.vrf_lites.{policy['name']}.bgp. " + f"BGP and {ospf_version.upper()} are defined in the same vrf-lite entry; " + "please use two different vrf-lite entries." + ) + + if {"ospf", "ospfv3"}.issubset(policy): cls.results.append( f"vxlan.overlay_extensions.vrf_lites.{policy['name']}.ospf, " - f"vxlan.overlay_extensions.vrf_lites.{policy['name']}.bgp. " - "BGP and OSPF are defined in the same vrf-lite entry; " + f"vxlan.overlay_extensions.vrf_lites.{policy['name']}.ospfv3. " + "OSPF and OSPFv3 are defined in the same vrf-lite entry; " "please use two different vrf-lite entries." ) @@ -103,29 +114,31 @@ def check_global_ospf_process(cls, policy): """ Check OSPF Process """ - if policy.get("ospf") and not policy["ospf"].get("process"): - cls.results.append( - f"vxlan.overlay_extensions.vrf_lites.{policy['name']}.ospf.process. " - f"OSPF process is not defined." - ) + for ospf_version in OSPF_VERSIONS: + if policy.get(ospf_version) and not policy[ospf_version].get("process"): + cls.results.append( + f"vxlan.overlay_extensions.vrf_lites.{policy['name']}.{ospf_version}.process. " + f"{ospf_version.upper()} process is not defined." + ) @classmethod def check_global_ospf_area(cls, policy): """ Check OSPF if backbone area is standard """ - if policy.get("ospf") and not policy["ospf"].get("areas"): - for area in policy["ospf"]["areas"]: - if "id" in area and area.get("area_type"): - # Check if AREA 0 is not standard - if area["id"] in (0, "0.0.0.0") and area["area_type"] != "standard": - cls.results.append( - f"vxlan.overlay_extensions.vrf_lites.{policy['name']}.ospf.areas.id.0. " - f"area_type is defined to {area['area_type']}. " - "Backbone area is always standard" - ) - elif area["area_type"] == "nssa": - cls.check_global_ospf_nssa(area, policy["name"]) + for ospf_version in OSPF_VERSIONS: + if policy.get(ospf_version) and policy[ospf_version].get("areas"): + for area in policy[ospf_version]["areas"]: + if "id" in area and area.get("area_type"): + # Check if AREA 0 is not standard + if area["id"] in (0, "0.0.0.0") and area["area_type"] != "standard": + cls.results.append( + f"vxlan.overlay_extensions.vrf_lites.{policy['name']}.{ospf_version}.areas.id.0. " + f"area_type is defined to {area['area_type']}. " + "Backbone area is always standard" + ) + elif area["area_type"] == "nssa": + cls.check_global_ospf_nssa(area, policy["name"]) @classmethod def check_global_ospf_nssa(cls, area, policy): @@ -165,6 +178,7 @@ def check_switch_level( Check switch level """ ospf = False + ospfv3 = False bgp = False # Check (bgp or bgp_peer) at the switch level @@ -190,12 +204,35 @@ def check_switch_level( policy["name"], ) - # Check if OSPF and BGP is enabled - if ospf is True and bgp is True: + # Check OSPFv3 at the switch level + if switch_policy.get("interfaces", None): + for interface in switch_policy["interfaces"]: + if interface.get("ospfv3"): + ospfv3 = True + cls.check_switch_ospf( + interface["ospfv3"], + switch_policy["name"], + interface["name"], + policy["name"], + ) + + # Check if OSPF, OSPFv3 or BGP is enabled + if (ospf or ospfv3) and bgp: + ospf_ver_str = "" + ospf_ver_str = "OSPF" if ospf else "" + ospf_ver_str += ", " if ospf and ospfv3 else "" + ospf_ver_str += "OSPFv3" if ospfv3 else "" + + cls.results.append( + f"vxlan.overlay_extensions.vrf_lites.{policy['name']}.switches.{switch_policy['name']}. " + f"BGP, {ospf_ver_str} are configured in the same policy at the switch level. " + "Please use two different policies.-xx" + ) + if ospf and ospfv3: cls.results.append( f"vxlan.overlay_extensions.vrf_lites.{policy['name']}.switches.{switch_policy['name']}. " - "BGP and OSPF are configured in the same policy at the switch level. " - "Please use two different policies" + "OSPF and OSPFv3 are configured in the same policy at the switch level. " + "Please use two different policies." ) # Check if switch exists in topology