From fd83f7df08ba86b0d3a24b0c3d6c4bdb9fd30389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C5=82awomir=20Kaszlikowski?= Date: Fri, 14 Nov 2025 14:57:50 +0100 Subject: [PATCH 01/14] Fix for #393 [ND3.1.x] [eBGP fabric] ANYCAST_RP_IP_RANGE is not deploying on NDFC https://wwwin-github.cisco.com/netascode/nac-vxlan/issues/393 --- .../ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 index 24732dfb8..6bb06a5aa 100644 --- a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 +++ b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 @@ -17,6 +17,7 @@ REPLICATION_MODE: {{ vxlan.underlay.general.replication_mode | default(defaults.vxlan.underlay.general.replication_mode) | title }} {% if not (vxlan.underlay.general.manual_underlay_allocation | default(defaults.vxlan.underlay.general.manual_underlay_allocation) | ansible.builtin.bool) %} {% if not (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay) | ansible.builtin.bool) %} + ANYCAST_RP_IP_RANGE: {{ vxlan.underlay.ipv4.underlay_rp_loopback_ip_range | default(defaults.vxlan.underlay.ipv4.underlay_rp_loopback_ip_range) }} LOOPBACK1_IP_RANGE: {{ vxlan.underlay.ipv4.underlay_vtep_loopback_ip_range | default(defaults.vxlan.underlay.ipv4.underlay_vtep_loopback_ip_range) }} {% if (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay) | ansible.builtin.bool) %} LOOPBACK1_IPV6_RANGE: {{ vxlan.underlay.ipv6.underlay_vtep_loopback_ip_range | default(defaults.vxlan.underlay.ipv6.underlay_vtep_loopback_ip_range) }} @@ -35,9 +36,6 @@ ENABLE_TRMv6: {{ vxlan.underlay.multicast.ipv6.trmv6_enable | default(defaults.vxlan.underlay.multicast.ipv6.trmv6_enable) | title }} {% endif %} {% if not (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay) | ansible.builtin.bool) %} -{% if not (vxlan.underlay.general.manual_underlay_allocation | default(defaults.vxlan.underlay.general.manual_underlay_allocation) | ansible.builtin.bool) %} - ANYCAST_RP_IP_RANGE: {{ vxlan.underlay.ipv4.underlay_rp_loopback_ip_range | default(defaults.vxlan.underlay.ipv4.underlay_rp_loopback_ip_range) }} -{% endif %} MULTICAST_GROUP_SUBNET: {{ vxlan.underlay.multicast.ipv4.group_subnet | default(defaults.vxlan.underlay.multicast.ipv4.group_subnet) }} {# {% if (vxlan.underlay.multicast.ipv4.trm_enable | default(defaults.vxlan.underlay.multicast.ipv4.trm_enable) | ansible.builtin.bool) %} #} {# L3VNI_MCAST_GROUP: {{ vxlan.underlay.multicast.ipv4.trm_default_group | default(defaults.vxlan.underlay.multicast.ipv4.trm_default_group) }} #} From 49b6d8acd4d52a36bc1035454e4269d0ae344027 Mon Sep 17 00:00:00 2001 From: "Slawomir Kaszlikowski (skaszlik)" Date: Mon, 17 Nov 2025 15:12:19 +0100 Subject: [PATCH 02/14] Refactor eBGP VXLAN EVPN template for improved readability and maintainability --- .../evpn/ebgp_vxlan_fabric_evpn.j2 | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 index 6bb06a5aa..5d04c6143 100644 --- a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 +++ b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 @@ -1,7 +1,14 @@ {# Auto-generated NDFC eBGP VXLAN EVPN config data structure for fabric {{ vxlan.fabric.name }} #} +{% set manual_underlay = (vxlan.underlay.general.manual_underlay_allocation | default(defaults.vxlan.underlay.general.manual_underlay_allocation)) %} +{% set ipv6_underlay = (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay)) %} +{% set replication_mode = (vxlan.underlay.general.replication_mode | default(defaults.vxlan.underlay.general.replication_mode) | title) %} +{% set rp_mode = vxlan.underlay.multicast.rp_mode | default(defaults.vxlan.underlay.multicast.rp_mode) %} +{% set rp_count = vxlan.underlay.multicast.rendezvous_points | default(defaults.vxlan.underlay.multicast.rendezvous_points) %} +{% set ndfc_ge_12_2_2 = ndfc_version | cisco.nac_dc_vxlan.version_compare('12.2.2', '>=') %} +{% set ndfc_lt_12_4_1 = ndfc_version | cisco.nac_dc_vxlan.version_compare('12.4.1', '<') %} ENABLE_EVPN: true OVERLAY_MODE: {{ vxlan.global.ebgp.overlay_mode | default(defaults.vxlan.global.ebgp.overlay_mode) }} -{% if ndfc_version | cisco.nac_dc_vxlan.version_compare('12.2.2', '>=') and ndfc_version | cisco.nac_dc_vxlan.version_compare('12.4.1', '<') %} +{% if ndfc_ge_12_2_2 and ndfc_lt_12_4_1 %} ALLOW_L3VNI_NO_VLAN: {{ vxlan.global.ebgp.enable_mvpn_vri_id_range | default(defaults.vxlan.global.ebgp.enable_mvpn_vri_id_range) }} {% endif %} ENABLE_L3VNI_NO_VLAN: {{ vxlan.global.ebgp.enable_l3_vni_no_vlan | default(defaults.vxlan.global.ebgp.enable_l3_vni_no_vlan) }} @@ -14,52 +21,48 @@ {% if not (vxlan.global.ebgp.vpc.advertise_pip | default(defaults.vxlan.global.ebgp.vpc.advertise_pip) | ansible.builtin.bool) %} ADVERTISE_PIP_ON_BORDER: {{ vxlan.global.ebgp.vpc.advertise_pip_border_only | default(defaults.vxlan.global.ebgp.vpc.advertise_pip_border_only) | title }} {% endif %} - REPLICATION_MODE: {{ vxlan.underlay.general.replication_mode | default(defaults.vxlan.underlay.general.replication_mode) | title }} -{% if not (vxlan.underlay.general.manual_underlay_allocation | default(defaults.vxlan.underlay.general.manual_underlay_allocation) | ansible.builtin.bool) %} -{% if not (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay) | ansible.builtin.bool) %} - ANYCAST_RP_IP_RANGE: {{ vxlan.underlay.ipv4.underlay_rp_loopback_ip_range | default(defaults.vxlan.underlay.ipv4.underlay_rp_loopback_ip_range) }} + REPLICATION_MODE: {{ replication_mode }} +{% if not manual_underlay %} +{% if not ipv6_underlay %} LOOPBACK1_IP_RANGE: {{ vxlan.underlay.ipv4.underlay_vtep_loopback_ip_range | default(defaults.vxlan.underlay.ipv4.underlay_vtep_loopback_ip_range) }} -{% if (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay) | ansible.builtin.bool) %} +{% else %} LOOPBACK1_IPV6_RANGE: {{ vxlan.underlay.ipv6.underlay_vtep_loopback_ip_range | default(defaults.vxlan.underlay.ipv6.underlay_vtep_loopback_ip_range) }} {% endif %} {% endif %} -{% endif %} -{% if ( ((ndfc_version | cisco.nac_dc_vxlan.version_compare('12.2.1', '<=')) and - (not (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay) | ansible.builtin.bool))) or - (ndfc_version | cisco.nac_dc_vxlan.version_compare('12.2.2', '>=')) ) %} -{% if (vxlan.underlay.general.replication_mode | default(defaults.vxlan.underlay.general.replication_mode) | title) == 'Multicast' %} +{% if replication_mode == 'Multicast' %} RP_LB_ID: {{ vxlan.underlay.multicast.underlay_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_rp_loopback_id) }} - RP_COUNT: "{{ vxlan.underlay.multicast.rendezvous_points | default(defaults.vxlan.underlay.multicast.rendezvous_points) }}" - RP_MODE: {{ vxlan.underlay.multicast.rp_mode | default(defaults.vxlan.underlay.multicast.rp_mode) }} + RP_COUNT: "{{ rp_count }}" + RP_MODE: {{ rp_mode }} ENABLE_TRM: {{ vxlan.underlay.multicast.ipv4.trm_enable | default(defaults.vxlan.underlay.multicast.ipv4.trm_enable) | title }} -{% if (ndfc_version | cisco.nac_dc_vxlan.version_compare('12.2.2', '>=')) %} +{% if ndfc_ge_12_2_2 %} ENABLE_TRMv6: {{ vxlan.underlay.multicast.ipv6.trmv6_enable | default(defaults.vxlan.underlay.multicast.ipv6.trmv6_enable) | title }} {% endif %} -{% if not (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay) | ansible.builtin.bool) %} +{% if not ipv6_underlay %} +{% if not manual_underlay %} + ANYCAST_RP_IP_RANGE: {{ vxlan.underlay.ipv4.underlay_rp_loopback_ip_range | default(defaults.vxlan.underlay.ipv4.underlay_rp_loopback_ip_range) }} +{% endif %} MULTICAST_GROUP_SUBNET: {{ vxlan.underlay.multicast.ipv4.group_subnet | default(defaults.vxlan.underlay.multicast.ipv4.group_subnet) }} {# {% if (vxlan.underlay.multicast.ipv4.trm_enable | default(defaults.vxlan.underlay.multicast.ipv4.trm_enable) | ansible.builtin.bool) %} #} {# L3VNI_MCAST_GROUP: {{ vxlan.underlay.multicast.ipv4.trm_default_group | default(defaults.vxlan.underlay.multicast.ipv4.trm_default_group) }} #} {# {% endif %} #} -{% if ( (ndfc_version | cisco.nac_dc_vxlan.version_compare('12.2.2', '>=')) and - (vxlan.underlay.multicast.ipv6.trmv6_enable | default(defaults.vxlan.underlay.multicast.ipv6.trmv6_enable) | ansible.builtin.bool) ) %} +{% if ndfc_ge_12_2_2 and (vxlan.underlay.multicast.ipv6.trmv6_enable | default(defaults.vxlan.underlay.multicast.ipv6.trmv6_enable) | ansible.builtin.bool) %} L3VNI_IPv6_MCAST_GROUP: "{{ vxlan.underlay.multicast.ipv6.trmv6_default_group | default(defaults.vxlan.underlay.multicast.ipv6.trmv6_default_group) }}" {% endif %} -{% if vxlan.underlay.multicast.rp_mode | default(defaults.vxlan.underlay.multicast.rp_mode) == 'bidir' %} +{% if rp_mode == 'bidir' %} PHANTOM_RP_LB_ID1: {{ vxlan.underlay.multicast.underlay_primary_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_primary_rp_loopback_id) }} PHANTOM_RP_LB_ID2: {{ vxlan.underlay.multicast.underlay_backup_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_backup_rp_loopback_id) }} -{% if vxlan.underlay.multicast.rendezvous_points | default(defaults.vxlan.underlay.multicast.rendezvous_points) == 4 %} +{% if rp_count == 4 %} PHANTOM_RP_LB_ID3: {{ vxlan.underlay.multicast.underlay_second_backup_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_second_backup_rp_loopback_id) }} PHANTOM_RP_LB_ID4: {{ vxlan.underlay.multicast.underlay_third_backup_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_third_backup_rp_loopback_id) }} {% endif %} {% endif %} -{% elif (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay) | ansible.builtin.bool) %} -{% if not (vxlan.underlay.general.manual_underlay_allocation | default(defaults.vxlan.underlay.general.manual_underlay_allocation) | ansible.builtin.bool) %} +{% else %} +{% if not manual_underlay %} IPv6_ANYCAST_RP_IP_RANGE: {{ vxlan.underlay.ipv6.underlay_rp_loopback_ip_range | default(defaults.vxlan.underlay.ipv6.underlay_rp_loopback_ip_range) }} {% endif %} IPv6_MULTICAST_GROUP_SUBNET: {{ vxlan.underlay.multicast.ipv6.group_subnet | default(defaults.vxlan.underlay.multicast.ipv6.group_subnet) }} {% endif %} {% endif %} -{% endif %} {% if vxlan.global.ebgp.layer2_vni_range.from is defined %} {% set l2_vni_start = vxlan.global.ebgp.layer2_vni_range.from %} {% if vxlan.global.ebgp.layer2_vni_range.to is defined %} From fad461b671d05612c3d155034f4292378e94fc82 Mon Sep 17 00:00:00 2001 From: "Slawomir Kaszlikowski (skaszlik)" Date: Mon, 17 Nov 2025 15:38:29 +0100 Subject: [PATCH 03/14] Add support for L3VNI without VLAN in eBGP VXLAN EVPN configuration --- .../ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 index 5d04c6143..10114aa3b 100644 --- a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 +++ b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 @@ -6,12 +6,14 @@ {% set rp_count = vxlan.underlay.multicast.rendezvous_points | default(defaults.vxlan.underlay.multicast.rendezvous_points) %} {% set ndfc_ge_12_2_2 = ndfc_version | cisco.nac_dc_vxlan.version_compare('12.2.2', '>=') %} {% set ndfc_lt_12_4_1 = ndfc_version | cisco.nac_dc_vxlan.version_compare('12.4.1', '<') %} +{% set ndfc_ge_12_4_1 = ndfc_version | cisco.nac_dc_vxlan.version_compare('12.4.1', '>') %} ENABLE_EVPN: true OVERLAY_MODE: {{ vxlan.global.ebgp.overlay_mode | default(defaults.vxlan.global.ebgp.overlay_mode) }} {% if ndfc_ge_12_2_2 and ndfc_lt_12_4_1 %} ALLOW_L3VNI_NO_VLAN: {{ vxlan.global.ebgp.enable_mvpn_vri_id_range | default(defaults.vxlan.global.ebgp.enable_mvpn_vri_id_range) }} -{% endif %} + {% elif ndfc_ge_12_4_1 %} ENABLE_L3VNI_NO_VLAN: {{ vxlan.global.ebgp.enable_l3_vni_no_vlan | default(defaults.vxlan.global.ebgp.enable_l3_vni_no_vlan) }} + {% endif %} ANYCAST_GW_MAC: {{ vxlan.global.ebgp.anycast_gateway_mac | default(defaults.vxlan.global.ebgp.anycast_gateway_mac) }} ADVERTISE_PIP_BGP: {{ (vxlan.global.ebgp.vpc.advertise_pip | default(defaults.vxlan.global.ebgp.vpc.advertise_pip) | title) }} {% if vxlan.global.ebgp.multisite_site_id is defined %} From eeeab31475bfc10a096d0da4de320c739b9f05aa Mon Sep 17 00:00:00 2001 From: "Slawomir Kaszlikowski (skaszlik)" Date: Mon, 17 Nov 2025 15:44:26 +0100 Subject: [PATCH 04/14] Add comments for better reading --- .../evpn/ebgp_vxlan_fabric_evpn.j2 | 54 ++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 index 10114aa3b..85c693019 100644 --- a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 +++ b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 @@ -9,68 +9,99 @@ {% set ndfc_ge_12_4_1 = ndfc_version | cisco.nac_dc_vxlan.version_compare('12.4.1', '>') %} ENABLE_EVPN: true OVERLAY_MODE: {{ vxlan.global.ebgp.overlay_mode | default(defaults.vxlan.global.ebgp.overlay_mode) }} +{# IF: NDFC between 12.2.2 and 12.4.0 START #} {% if ndfc_ge_12_2_2 and ndfc_lt_12_4_1 %} ALLOW_L3VNI_NO_VLAN: {{ vxlan.global.ebgp.enable_mvpn_vri_id_range | default(defaults.vxlan.global.ebgp.enable_mvpn_vri_id_range) }} - {% elif ndfc_ge_12_4_1 %} +{% elif ndfc_ge_12_4_1 %} ENABLE_L3VNI_NO_VLAN: {{ vxlan.global.ebgp.enable_l3_vni_no_vlan | default(defaults.vxlan.global.ebgp.enable_l3_vni_no_vlan) }} - {% endif %} +{% endif %} +{# IF: NDFC between 12.2.2 and 12.4.0 END #} ANYCAST_GW_MAC: {{ vxlan.global.ebgp.anycast_gateway_mac | default(defaults.vxlan.global.ebgp.anycast_gateway_mac) }} ADVERTISE_PIP_BGP: {{ (vxlan.global.ebgp.vpc.advertise_pip | default(defaults.vxlan.global.ebgp.vpc.advertise_pip) | title) }} +{# IF: Multisite SITE_ID START #} {% if vxlan.global.ebgp.multisite_site_id is defined %} SITE_ID: {{ vxlan.global.ebgp.multisite_site_id | default(vxlan.global.ebgp.spine_bgp_asn) }} {% endif %} +{# IF: Multisite SITE_ID END #} ANYCAST_BGW_ADVERTISE_PIP: {{ vxlan.global.ebgp.vpc.advertise_pip_border_gateway | default(defaults.vxlan.global.ebgp.vpc.advertise_pip_border_gateway) }} +{# IF: Advertise PIP toggle START #} {% if not (vxlan.global.ebgp.vpc.advertise_pip | default(defaults.vxlan.global.ebgp.vpc.advertise_pip) | ansible.builtin.bool) %} ADVERTISE_PIP_ON_BORDER: {{ vxlan.global.ebgp.vpc.advertise_pip_border_only | default(defaults.vxlan.global.ebgp.vpc.advertise_pip_border_only) | title }} {% endif %} +{# IF: Advertise PIP toggle END #} REPLICATION_MODE: {{ replication_mode }} +{# IF: Manual underlay disabled START #} {% if not manual_underlay %} +{# IF: IPv4 underlay START #} {% if not ipv6_underlay %} LOOPBACK1_IP_RANGE: {{ vxlan.underlay.ipv4.underlay_vtep_loopback_ip_range | default(defaults.vxlan.underlay.ipv4.underlay_vtep_loopback_ip_range) }} {% else %} LOOPBACK1_IPV6_RANGE: {{ vxlan.underlay.ipv6.underlay_vtep_loopback_ip_range | default(defaults.vxlan.underlay.ipv6.underlay_vtep_loopback_ip_range) }} {% endif %} +{# IF: IPv4 underlay END #} {% endif %} +{# IF: Manual underlay disabled END #} +{# IF: Replication mode multicast START #} {% if replication_mode == 'Multicast' %} RP_LB_ID: {{ vxlan.underlay.multicast.underlay_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_rp_loopback_id) }} RP_COUNT: "{{ rp_count }}" RP_MODE: {{ rp_mode }} ENABLE_TRM: {{ vxlan.underlay.multicast.ipv4.trm_enable | default(defaults.vxlan.underlay.multicast.ipv4.trm_enable) | title }} + {# IF: NDFC >= 12.2.2 START #} {% if ndfc_ge_12_2_2 %} ENABLE_TRMv6: {{ vxlan.underlay.multicast.ipv6.trmv6_enable | default(defaults.vxlan.underlay.multicast.ipv6.trmv6_enable) | title }} {% endif %} + {# IF: NDFC >= 12.2.2 END #} + {# IF: IPv4 multicast START #} {% if not ipv6_underlay %} + {# IF: Manual underlay disabled (IPv4 multicast) START #} {% if not manual_underlay %} ANYCAST_RP_IP_RANGE: {{ vxlan.underlay.ipv4.underlay_rp_loopback_ip_range | default(defaults.vxlan.underlay.ipv4.underlay_rp_loopback_ip_range) }} {% endif %} + {# IF: Manual underlay disabled (IPv4 multicast) END #} MULTICAST_GROUP_SUBNET: {{ vxlan.underlay.multicast.ipv4.group_subnet | default(defaults.vxlan.underlay.multicast.ipv4.group_subnet) }} {# {% if (vxlan.underlay.multicast.ipv4.trm_enable | default(defaults.vxlan.underlay.multicast.ipv4.trm_enable) | ansible.builtin.bool) %} #} {# L3VNI_MCAST_GROUP: {{ vxlan.underlay.multicast.ipv4.trm_default_group | default(defaults.vxlan.underlay.multicast.ipv4.trm_default_group) }} #} {# {% endif %} #} + {# IF: TRMv6 group START #} {% if ndfc_ge_12_2_2 and (vxlan.underlay.multicast.ipv6.trmv6_enable | default(defaults.vxlan.underlay.multicast.ipv6.trmv6_enable) | ansible.builtin.bool) %} L3VNI_IPv6_MCAST_GROUP: "{{ vxlan.underlay.multicast.ipv6.trmv6_default_group | default(defaults.vxlan.underlay.multicast.ipv6.trmv6_default_group) }}" {% endif %} + {# IF: TRMv6 group END #} + {# IF: RP mode bidir START #} {% if rp_mode == 'bidir' %} PHANTOM_RP_LB_ID1: {{ vxlan.underlay.multicast.underlay_primary_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_primary_rp_loopback_id) }} PHANTOM_RP_LB_ID2: {{ vxlan.underlay.multicast.underlay_backup_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_backup_rp_loopback_id) }} + {# IF: RP count equals 4 START #} {% if rp_count == 4 %} PHANTOM_RP_LB_ID3: {{ vxlan.underlay.multicast.underlay_second_backup_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_second_backup_rp_loopback_id) }} PHANTOM_RP_LB_ID4: {{ vxlan.underlay.multicast.underlay_third_backup_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_third_backup_rp_loopback_id) }} {% endif %} + {# IF: RP count equals 4 END #} {% endif %} + {# IF: RP mode bidir END #} {% else %} + {# IF: IPv6 multicast START #} {% if not manual_underlay %} IPv6_ANYCAST_RP_IP_RANGE: {{ vxlan.underlay.ipv6.underlay_rp_loopback_ip_range | default(defaults.vxlan.underlay.ipv6.underlay_rp_loopback_ip_range) }} {% endif %} IPv6_MULTICAST_GROUP_SUBNET: {{ vxlan.underlay.multicast.ipv6.group_subnet | default(defaults.vxlan.underlay.multicast.ipv6.group_subnet) }} + {# IF: IPv6 multicast END #} {% endif %} + {# IF: IPv4 multicast END #} {% endif %} +{# IF: Replication mode multicast END #} +{# IF: L2 VNI start defined START #} {% if vxlan.global.ebgp.layer2_vni_range.from is defined %} {% set l2_vni_start = vxlan.global.ebgp.layer2_vni_range.from %} + {# IF: L2 VNI end defined START #} {% if vxlan.global.ebgp.layer2_vni_range.to is defined %} {% set l2_vni_end = vxlan.global.ebgp.layer2_vni_range.to %} {% endif %} + {# IF: L2 VNI end defined END #} {% endif %} +{# IF: L2 VNI start defined END #} +{# IF: L2 VNI range derive START #} {% if l2_vni_start is defined and l2_vni_end is not defined %} {% set l2_vni_range = l2_vni_start %} {% elif l2_vni_start is defined and l2_vni_end is defined %} @@ -78,13 +109,19 @@ {% else %} {% set l2_vni_range = defaults.vxlan.global.ebgp.layer2_vni_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer2_vni_range.to %} {% endif %} +{# IF: L2 VNI range derive END #} L2_SEGMENT_ID_RANGE: {{ l2_vni_range }} +{# IF: L3 VNI start defined START #} {% if vxlan.global.ebgp.layer3_vni_range.from is defined %} {% set l3_vni_start = vxlan.global.ebgp.layer3_vni_range.from %} + {# IF: L3 VNI end defined START #} {% if vxlan.global.ebgp.layer3_vni_range.to is defined %} {% set l3_vni_end = vxlan.global.ebgp.layer3_vni_range.to %} {% endif %} + {# IF: L3 VNI end defined END #} {% endif %} +{# IF: L3 VNI start defined END #} +{# IF: L3 VNI range derive START #} {% if l3_vni_start is defined and l3_vni_end is not defined %} {% set l3_vni_range = l3_vni_start %} {% elif l3_vni_start is defined and l3_vni_end is defined %} @@ -92,13 +129,19 @@ {% else %} {% set l3_vni_range = defaults.vxlan.global.ebgp.layer3_vni_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer3_vni_range.to %} {% endif %} +{# IF: L3 VNI range derive END #} L3_PARTITION_ID_RANGE: {{ l3_vni_range }} +{# IF: L2 VLAN start defined START #} {% if vxlan.global.ebgp.layer2_vlan_range.from is defined %} {% set l2_vlan_start = vxlan.global.ebgp.layer2_vlan_range.from %} + {# IF: L2 VLAN end defined START #} {% if vxlan.global.ebgp.layer2_vlan_range.to is defined %} {% set l2_vlan_end = vxlan.global.ebgp.layer2_vlan_range.to %} {% endif %} + {# IF: L2 VLAN end defined END #} {% endif %} +{# IF: L2 VLAN start defined END #} +{# IF: L2 VLAN range derive START #} {% if l2_vlan_start is defined and l2_vlan_end is not defined %} {% set l2_vlan_range = l2_vlan_start %} {% elif l2_vlan_start is defined and l2_vlan_end is defined %} @@ -106,13 +149,19 @@ {% else %} {% set l2_vlan_range = defaults.vxlan.global.ebgp.layer2_vlan_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer2_vlan_range.to %} {% endif %} +{# IF: L2 VLAN range derive END #} NETWORK_VLAN_RANGE: {{ l2_vlan_range }} +{# IF: L3 VLAN start defined START #} {% if vxlan.global.ebgp.layer3_vlan_range.from is defined %} {% set l3_vlan_start = vxlan.global.ebgp.layer3_vlan_range.from %} + {# IF: L3 VLAN end defined START #} {% if vxlan.global.ebgp.layer3_vlan_range.to is defined %} {% set l3_vlan_end = vxlan.global.ebgp.layer3_vlan_range.to %} {% endif %} + {# IF: L3 VLAN end defined END #} {% endif %} +{# IF: L3 VLAN start defined END #} +{# IF: L3 VLAN range derive START #} {% if l3_vlan_start is defined and l3_vlan_end is not defined %} {% set l3_vlan_range = l3_vlan_start %} {% elif l3_vlan_start is defined and l3_vlan_end is defined %} @@ -120,4 +169,5 @@ {% else %} {% set l3_vlan_range = defaults.vxlan.global.ebgp.layer3_vlan_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer3_vlan_range.to %} {% endif %} +{# IF: L3 VLAN range derive END #} VRF_VLAN_RANGE: {{ l3_vlan_range }} From ef321e9fe2ed788aed26da6ccbe1a95f615903b1 Mon Sep 17 00:00:00 2001 From: "Slawomir Kaszlikowski (skaszlik)" Date: Mon, 17 Nov 2025 17:05:00 +0100 Subject: [PATCH 05/14] Refactor eBGP VXLAN EVPN template to enhance readability and maintainability --- .../evpn/ebgp_vxlan_fabric_evpn.j2 | 153 ++++++------------ 1 file changed, 50 insertions(+), 103 deletions(-) diff --git a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 index 85c693019..2f11ae532 100644 --- a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 +++ b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 @@ -9,165 +9,112 @@ {% set ndfc_ge_12_4_1 = ndfc_version | cisco.nac_dc_vxlan.version_compare('12.4.1', '>') %} ENABLE_EVPN: true OVERLAY_MODE: {{ vxlan.global.ebgp.overlay_mode | default(defaults.vxlan.global.ebgp.overlay_mode) }} -{# IF: NDFC between 12.2.2 and 12.4.0 START #} {% if ndfc_ge_12_2_2 and ndfc_lt_12_4_1 %} ALLOW_L3VNI_NO_VLAN: {{ vxlan.global.ebgp.enable_mvpn_vri_id_range | default(defaults.vxlan.global.ebgp.enable_mvpn_vri_id_range) }} {% elif ndfc_ge_12_4_1 %} ENABLE_L3VNI_NO_VLAN: {{ vxlan.global.ebgp.enable_l3_vni_no_vlan | default(defaults.vxlan.global.ebgp.enable_l3_vni_no_vlan) }} {% endif %} -{# IF: NDFC between 12.2.2 and 12.4.0 END #} ANYCAST_GW_MAC: {{ vxlan.global.ebgp.anycast_gateway_mac | default(defaults.vxlan.global.ebgp.anycast_gateway_mac) }} ADVERTISE_PIP_BGP: {{ (vxlan.global.ebgp.vpc.advertise_pip | default(defaults.vxlan.global.ebgp.vpc.advertise_pip) | title) }} -{# IF: Multisite SITE_ID START #} {% if vxlan.global.ebgp.multisite_site_id is defined %} SITE_ID: {{ vxlan.global.ebgp.multisite_site_id | default(vxlan.global.ebgp.spine_bgp_asn) }} {% endif %} -{# IF: Multisite SITE_ID END #} ANYCAST_BGW_ADVERTISE_PIP: {{ vxlan.global.ebgp.vpc.advertise_pip_border_gateway | default(defaults.vxlan.global.ebgp.vpc.advertise_pip_border_gateway) }} -{# IF: Advertise PIP toggle START #} {% if not (vxlan.global.ebgp.vpc.advertise_pip | default(defaults.vxlan.global.ebgp.vpc.advertise_pip) | ansible.builtin.bool) %} ADVERTISE_PIP_ON_BORDER: {{ vxlan.global.ebgp.vpc.advertise_pip_border_only | default(defaults.vxlan.global.ebgp.vpc.advertise_pip_border_only) | title }} {% endif %} -{# IF: Advertise PIP toggle END #} REPLICATION_MODE: {{ replication_mode }} -{# IF: Manual underlay disabled START #} {% if not manual_underlay %} -{# IF: IPv4 underlay START #} {% if not ipv6_underlay %} LOOPBACK1_IP_RANGE: {{ vxlan.underlay.ipv4.underlay_vtep_loopback_ip_range | default(defaults.vxlan.underlay.ipv4.underlay_vtep_loopback_ip_range) }} {% else %} LOOPBACK1_IPV6_RANGE: {{ vxlan.underlay.ipv6.underlay_vtep_loopback_ip_range | default(defaults.vxlan.underlay.ipv6.underlay_vtep_loopback_ip_range) }} {% endif %} -{# IF: IPv4 underlay END #} {% endif %} -{# IF: Manual underlay disabled END #} -{# IF: Replication mode multicast START #} {% if replication_mode == 'Multicast' %} RP_LB_ID: {{ vxlan.underlay.multicast.underlay_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_rp_loopback_id) }} RP_COUNT: "{{ rp_count }}" RP_MODE: {{ rp_mode }} ENABLE_TRM: {{ vxlan.underlay.multicast.ipv4.trm_enable | default(defaults.vxlan.underlay.multicast.ipv4.trm_enable) | title }} - {# IF: NDFC >= 12.2.2 START #} {% if ndfc_ge_12_2_2 %} ENABLE_TRMv6: {{ vxlan.underlay.multicast.ipv6.trmv6_enable | default(defaults.vxlan.underlay.multicast.ipv6.trmv6_enable) | title }} {% endif %} - {# IF: NDFC >= 12.2.2 END #} - {# IF: IPv4 multicast START #} {% if not ipv6_underlay %} - {# IF: Manual underlay disabled (IPv4 multicast) START #} {% if not manual_underlay %} ANYCAST_RP_IP_RANGE: {{ vxlan.underlay.ipv4.underlay_rp_loopback_ip_range | default(defaults.vxlan.underlay.ipv4.underlay_rp_loopback_ip_range) }} {% endif %} - {# IF: Manual underlay disabled (IPv4 multicast) END #} MULTICAST_GROUP_SUBNET: {{ vxlan.underlay.multicast.ipv4.group_subnet | default(defaults.vxlan.underlay.multicast.ipv4.group_subnet) }} -{# {% if (vxlan.underlay.multicast.ipv4.trm_enable | default(defaults.vxlan.underlay.multicast.ipv4.trm_enable) | ansible.builtin.bool) %} #} -{# L3VNI_MCAST_GROUP: {{ vxlan.underlay.multicast.ipv4.trm_default_group | default(defaults.vxlan.underlay.multicast.ipv4.trm_default_group) }} #} -{# {% endif %} #} - {# IF: TRMv6 group START #} {% if ndfc_ge_12_2_2 and (vxlan.underlay.multicast.ipv6.trmv6_enable | default(defaults.vxlan.underlay.multicast.ipv6.trmv6_enable) | ansible.builtin.bool) %} L3VNI_IPv6_MCAST_GROUP: "{{ vxlan.underlay.multicast.ipv6.trmv6_default_group | default(defaults.vxlan.underlay.multicast.ipv6.trmv6_default_group) }}" {% endif %} - {# IF: TRMv6 group END #} - {# IF: RP mode bidir START #} {% if rp_mode == 'bidir' %} PHANTOM_RP_LB_ID1: {{ vxlan.underlay.multicast.underlay_primary_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_primary_rp_loopback_id) }} PHANTOM_RP_LB_ID2: {{ vxlan.underlay.multicast.underlay_backup_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_backup_rp_loopback_id) }} - {# IF: RP count equals 4 START #} {% if rp_count == 4 %} PHANTOM_RP_LB_ID3: {{ vxlan.underlay.multicast.underlay_second_backup_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_second_backup_rp_loopback_id) }} PHANTOM_RP_LB_ID4: {{ vxlan.underlay.multicast.underlay_third_backup_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_third_backup_rp_loopback_id) }} {% endif %} - {# IF: RP count equals 4 END #} {% endif %} - {# IF: RP mode bidir END #} {% else %} - {# IF: IPv6 multicast START #} {% if not manual_underlay %} IPv6_ANYCAST_RP_IP_RANGE: {{ vxlan.underlay.ipv6.underlay_rp_loopback_ip_range | default(defaults.vxlan.underlay.ipv6.underlay_rp_loopback_ip_range) }} {% endif %} IPv6_MULTICAST_GROUP_SUBNET: {{ vxlan.underlay.multicast.ipv6.group_subnet | default(defaults.vxlan.underlay.multicast.ipv6.group_subnet) }} - {# IF: IPv6 multicast END #} -{% endif %} - {# IF: IPv4 multicast END #} -{% endif %} -{# IF: Replication mode multicast END #} -{# IF: L2 VNI start defined START #} -{% if vxlan.global.ebgp.layer2_vni_range.from is defined %} -{% set l2_vni_start = vxlan.global.ebgp.layer2_vni_range.from %} - {# IF: L2 VNI end defined START #} -{% if vxlan.global.ebgp.layer2_vni_range.to is defined %} -{% set l2_vni_end = vxlan.global.ebgp.layer2_vni_range.to %} -{% endif %} - {# IF: L2 VNI end defined END #} -{% endif %} -{# IF: L2 VNI start defined END #} -{# IF: L2 VNI range derive START #} -{% if l2_vni_start is defined and l2_vni_end is not defined %} -{% set l2_vni_range = l2_vni_start %} -{% elif l2_vni_start is defined and l2_vni_end is defined %} -{% set l2_vni_range = l2_vni_start ~ '-' ~ l2_vni_end %} -{% else %} -{% set l2_vni_range = defaults.vxlan.global.ebgp.layer2_vni_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer2_vni_range.to %} {% endif %} -{# IF: L2 VNI range derive END #} +{% endif %} +{% if vxlan.global.ebgp.layer2_vni_range.from is defined -%} +{% set l2_vni_start = vxlan.global.ebgp.layer2_vni_range.from -%} +{% if vxlan.global.ebgp.layer2_vni_range.to is defined -%} +{% set l2_vni_end = vxlan.global.ebgp.layer2_vni_range.to -%} +{% endif -%} +{% endif -%} +{% if l2_vni_start is defined and l2_vni_end is not defined -%} +{% set l2_vni_range = l2_vni_start -%} +{% elif l2_vni_start is defined and l2_vni_end is defined -%} +{% set l2_vni_range = l2_vni_start ~ '-' ~ l2_vni_end -%} +{% else -%} +{% set l2_vni_range = defaults.vxlan.global.ebgp.layer2_vni_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer2_vni_range.to -%} +{% endif %} L2_SEGMENT_ID_RANGE: {{ l2_vni_range }} -{# IF: L3 VNI start defined START #} -{% if vxlan.global.ebgp.layer3_vni_range.from is defined %} -{% set l3_vni_start = vxlan.global.ebgp.layer3_vni_range.from %} - {# IF: L3 VNI end defined START #} -{% if vxlan.global.ebgp.layer3_vni_range.to is defined %} -{% set l3_vni_end = vxlan.global.ebgp.layer3_vni_range.to %} -{% endif %} - {# IF: L3 VNI end defined END #} -{% endif %} -{# IF: L3 VNI start defined END #} -{# IF: L3 VNI range derive START #} -{% if l3_vni_start is defined and l3_vni_end is not defined %} -{% set l3_vni_range = l3_vni_start %} -{% elif l3_vni_start is defined and l3_vni_end is defined %} -{% set l3_vni_range = l3_vni_start ~ '-' ~ l3_vni_end %} -{% else %} -{% set l3_vni_range = defaults.vxlan.global.ebgp.layer3_vni_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer3_vni_range.to %} +{% if vxlan.global.ebgp.layer3_vni_range.from is defined -%} +{% set l3_vni_start = vxlan.global.ebgp.layer3_vni_range.from -%} +{% if vxlan.global.ebgp.layer3_vni_range.to is defined -%} +{% set l3_vni_end = vxlan.global.ebgp.layer3_vni_range.to -%} +{% endif -%} +{% endif -%} +{% if l3_vni_start is defined and l3_vni_end is not defined -%} +{% set l3_vni_range = l3_vni_start -%} +{% elif l3_vni_start is defined and l3_vni_end is defined -%} +{% set l3_vni_range = l3_vni_start ~ '-' ~ l3_vni_end -%} +{% else -%} +{% set l3_vni_range = defaults.vxlan.global.ebgp.layer3_vni_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer3_vni_range.to -%} {% endif %} -{# IF: L3 VNI range derive END #} L3_PARTITION_ID_RANGE: {{ l3_vni_range }} -{# IF: L2 VLAN start defined START #} -{% if vxlan.global.ebgp.layer2_vlan_range.from is defined %} -{% set l2_vlan_start = vxlan.global.ebgp.layer2_vlan_range.from %} - {# IF: L2 VLAN end defined START #} -{% if vxlan.global.ebgp.layer2_vlan_range.to is defined %} -{% set l2_vlan_end = vxlan.global.ebgp.layer2_vlan_range.to %} -{% endif %} - {# IF: L2 VLAN end defined END #} -{% endif %} -{# IF: L2 VLAN start defined END #} -{# IF: L2 VLAN range derive START #} -{% if l2_vlan_start is defined and l2_vlan_end is not defined %} -{% set l2_vlan_range = l2_vlan_start %} -{% elif l2_vlan_start is defined and l2_vlan_end is defined %} -{% set l2_vlan_range = l2_vlan_start ~ '-' ~ l2_vlan_end %} -{% else %} -{% set l2_vlan_range = defaults.vxlan.global.ebgp.layer2_vlan_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer2_vlan_range.to %} +{% if vxlan.global.ebgp.layer2_vlan_range.from is defined -%} +{% set l2_vlan_start = vxlan.global.ebgp.layer2_vlan_range.from -%} +{% if vxlan.global.ebgp.layer2_vlan_range.to is defined -%} +{% set l2_vlan_end = vxlan.global.ebgp.layer2_vlan_range.to -%} +{% endif -%} +{% endif -%} +{% if l2_vlan_start is defined and l2_vlan_end is not defined -%} +{% set l2_vlan_range = l2_vlan_start -%} +{% elif l2_vlan_start is defined and l2_vlan_end is defined -%} +{% set l2_vlan_range = l2_vlan_start ~ '-' ~ l2_vlan_end -%} +{% else -%} +{% set l2_vlan_range = defaults.vxlan.global.ebgp.layer2_vlan_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer2_vlan_range.to -%} {% endif %} -{# IF: L2 VLAN range derive END #} NETWORK_VLAN_RANGE: {{ l2_vlan_range }} -{# IF: L3 VLAN start defined START #} -{% if vxlan.global.ebgp.layer3_vlan_range.from is defined %} -{% set l3_vlan_start = vxlan.global.ebgp.layer3_vlan_range.from %} - {# IF: L3 VLAN end defined START #} -{% if vxlan.global.ebgp.layer3_vlan_range.to is defined %} -{% set l3_vlan_end = vxlan.global.ebgp.layer3_vlan_range.to %} -{% endif %} - {# IF: L3 VLAN end defined END #} -{% endif %} -{# IF: L3 VLAN start defined END #} -{# IF: L3 VLAN range derive START #} -{% if l3_vlan_start is defined and l3_vlan_end is not defined %} -{% set l3_vlan_range = l3_vlan_start %} -{% elif l3_vlan_start is defined and l3_vlan_end is defined %} -{% set l3_vlan_range = l3_vlan_start ~ '-' ~ l3_vlan_end %} -{% else %} -{% set l3_vlan_range = defaults.vxlan.global.ebgp.layer3_vlan_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer3_vlan_range.to %} +{% if vxlan.global.ebgp.layer3_vlan_range.from is defined -%} +{% set l3_vlan_start = vxlan.global.ebgp.layer3_vlan_range.from -%} +{% if vxlan.global.ebgp.layer3_vlan_range.to is defined -%} +{% set l3_vlan_end = vxlan.global.ebgp.layer3_vlan_range.to -%} +{% endif -%} +{% endif -%} +{% if l3_vlan_start is defined and l3_vlan_end is not defined -%} +{% set l3_vlan_range = l3_vlan_start -%} +{% elif l3_vlan_start is defined and l3_vlan_end is defined -%} +{% set l3_vlan_range = l3_vlan_start ~ '-' ~ l3_vlan_end -%} +{% else -%} +{% set l3_vlan_range = defaults.vxlan.global.ebgp.layer3_vlan_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer3_vlan_range.to -%} {% endif %} -{# IF: L3 VLAN range derive END #} VRF_VLAN_RANGE: {{ l3_vlan_range }} From 8437e868bb703de4eeaafa82e7504285df292256 Mon Sep 17 00:00:00 2001 From: "Slawomir Kaszlikowski (skaszlik)" Date: Tue, 18 Nov 2025 15:03:19 +0100 Subject: [PATCH 06/14] Refactor eBGP VXLAN EVPN template --- .../evpn/ebgp_vxlan_fabric_evpn.j2 | 148 +++++++++--------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 index 2f11ae532..24732dfb8 100644 --- a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 +++ b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 @@ -1,19 +1,10 @@ {# Auto-generated NDFC eBGP VXLAN EVPN config data structure for fabric {{ vxlan.fabric.name }} #} -{% set manual_underlay = (vxlan.underlay.general.manual_underlay_allocation | default(defaults.vxlan.underlay.general.manual_underlay_allocation)) %} -{% set ipv6_underlay = (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay)) %} -{% set replication_mode = (vxlan.underlay.general.replication_mode | default(defaults.vxlan.underlay.general.replication_mode) | title) %} -{% set rp_mode = vxlan.underlay.multicast.rp_mode | default(defaults.vxlan.underlay.multicast.rp_mode) %} -{% set rp_count = vxlan.underlay.multicast.rendezvous_points | default(defaults.vxlan.underlay.multicast.rendezvous_points) %} -{% set ndfc_ge_12_2_2 = ndfc_version | cisco.nac_dc_vxlan.version_compare('12.2.2', '>=') %} -{% set ndfc_lt_12_4_1 = ndfc_version | cisco.nac_dc_vxlan.version_compare('12.4.1', '<') %} -{% set ndfc_ge_12_4_1 = ndfc_version | cisco.nac_dc_vxlan.version_compare('12.4.1', '>') %} ENABLE_EVPN: true OVERLAY_MODE: {{ vxlan.global.ebgp.overlay_mode | default(defaults.vxlan.global.ebgp.overlay_mode) }} -{% if ndfc_ge_12_2_2 and ndfc_lt_12_4_1 %} +{% if ndfc_version | cisco.nac_dc_vxlan.version_compare('12.2.2', '>=') and ndfc_version | cisco.nac_dc_vxlan.version_compare('12.4.1', '<') %} ALLOW_L3VNI_NO_VLAN: {{ vxlan.global.ebgp.enable_mvpn_vri_id_range | default(defaults.vxlan.global.ebgp.enable_mvpn_vri_id_range) }} -{% elif ndfc_ge_12_4_1 %} - ENABLE_L3VNI_NO_VLAN: {{ vxlan.global.ebgp.enable_l3_vni_no_vlan | default(defaults.vxlan.global.ebgp.enable_l3_vni_no_vlan) }} {% endif %} + ENABLE_L3VNI_NO_VLAN: {{ vxlan.global.ebgp.enable_l3_vni_no_vlan | default(defaults.vxlan.global.ebgp.enable_l3_vni_no_vlan) }} ANYCAST_GW_MAC: {{ vxlan.global.ebgp.anycast_gateway_mac | default(defaults.vxlan.global.ebgp.anycast_gateway_mac) }} ADVERTISE_PIP_BGP: {{ (vxlan.global.ebgp.vpc.advertise_pip | default(defaults.vxlan.global.ebgp.vpc.advertise_pip) | title) }} {% if vxlan.global.ebgp.multisite_site_id is defined %} @@ -23,98 +14,107 @@ {% if not (vxlan.global.ebgp.vpc.advertise_pip | default(defaults.vxlan.global.ebgp.vpc.advertise_pip) | ansible.builtin.bool) %} ADVERTISE_PIP_ON_BORDER: {{ vxlan.global.ebgp.vpc.advertise_pip_border_only | default(defaults.vxlan.global.ebgp.vpc.advertise_pip_border_only) | title }} {% endif %} - REPLICATION_MODE: {{ replication_mode }} -{% if not manual_underlay %} -{% if not ipv6_underlay %} + REPLICATION_MODE: {{ vxlan.underlay.general.replication_mode | default(defaults.vxlan.underlay.general.replication_mode) | title }} +{% if not (vxlan.underlay.general.manual_underlay_allocation | default(defaults.vxlan.underlay.general.manual_underlay_allocation) | ansible.builtin.bool) %} +{% if not (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay) | ansible.builtin.bool) %} LOOPBACK1_IP_RANGE: {{ vxlan.underlay.ipv4.underlay_vtep_loopback_ip_range | default(defaults.vxlan.underlay.ipv4.underlay_vtep_loopback_ip_range) }} -{% else %} +{% if (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay) | ansible.builtin.bool) %} LOOPBACK1_IPV6_RANGE: {{ vxlan.underlay.ipv6.underlay_vtep_loopback_ip_range | default(defaults.vxlan.underlay.ipv6.underlay_vtep_loopback_ip_range) }} {% endif %} {% endif %} -{% if replication_mode == 'Multicast' %} +{% endif %} +{% if ( ((ndfc_version | cisco.nac_dc_vxlan.version_compare('12.2.1', '<=')) and + (not (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay) | ansible.builtin.bool))) or + (ndfc_version | cisco.nac_dc_vxlan.version_compare('12.2.2', '>=')) ) %} +{% if (vxlan.underlay.general.replication_mode | default(defaults.vxlan.underlay.general.replication_mode) | title) == 'Multicast' %} RP_LB_ID: {{ vxlan.underlay.multicast.underlay_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_rp_loopback_id) }} - RP_COUNT: "{{ rp_count }}" - RP_MODE: {{ rp_mode }} + RP_COUNT: "{{ vxlan.underlay.multicast.rendezvous_points | default(defaults.vxlan.underlay.multicast.rendezvous_points) }}" + RP_MODE: {{ vxlan.underlay.multicast.rp_mode | default(defaults.vxlan.underlay.multicast.rp_mode) }} ENABLE_TRM: {{ vxlan.underlay.multicast.ipv4.trm_enable | default(defaults.vxlan.underlay.multicast.ipv4.trm_enable) | title }} -{% if ndfc_ge_12_2_2 %} +{% if (ndfc_version | cisco.nac_dc_vxlan.version_compare('12.2.2', '>=')) %} ENABLE_TRMv6: {{ vxlan.underlay.multicast.ipv6.trmv6_enable | default(defaults.vxlan.underlay.multicast.ipv6.trmv6_enable) | title }} {% endif %} -{% if not ipv6_underlay %} -{% if not manual_underlay %} +{% if not (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay) | ansible.builtin.bool) %} +{% if not (vxlan.underlay.general.manual_underlay_allocation | default(defaults.vxlan.underlay.general.manual_underlay_allocation) | ansible.builtin.bool) %} ANYCAST_RP_IP_RANGE: {{ vxlan.underlay.ipv4.underlay_rp_loopback_ip_range | default(defaults.vxlan.underlay.ipv4.underlay_rp_loopback_ip_range) }} {% endif %} MULTICAST_GROUP_SUBNET: {{ vxlan.underlay.multicast.ipv4.group_subnet | default(defaults.vxlan.underlay.multicast.ipv4.group_subnet) }} -{% if ndfc_ge_12_2_2 and (vxlan.underlay.multicast.ipv6.trmv6_enable | default(defaults.vxlan.underlay.multicast.ipv6.trmv6_enable) | ansible.builtin.bool) %} +{# {% if (vxlan.underlay.multicast.ipv4.trm_enable | default(defaults.vxlan.underlay.multicast.ipv4.trm_enable) | ansible.builtin.bool) %} #} +{# L3VNI_MCAST_GROUP: {{ vxlan.underlay.multicast.ipv4.trm_default_group | default(defaults.vxlan.underlay.multicast.ipv4.trm_default_group) }} #} +{# {% endif %} #} +{% if ( (ndfc_version | cisco.nac_dc_vxlan.version_compare('12.2.2', '>=')) and + (vxlan.underlay.multicast.ipv6.trmv6_enable | default(defaults.vxlan.underlay.multicast.ipv6.trmv6_enable) | ansible.builtin.bool) ) %} L3VNI_IPv6_MCAST_GROUP: "{{ vxlan.underlay.multicast.ipv6.trmv6_default_group | default(defaults.vxlan.underlay.multicast.ipv6.trmv6_default_group) }}" {% endif %} -{% if rp_mode == 'bidir' %} +{% if vxlan.underlay.multicast.rp_mode | default(defaults.vxlan.underlay.multicast.rp_mode) == 'bidir' %} PHANTOM_RP_LB_ID1: {{ vxlan.underlay.multicast.underlay_primary_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_primary_rp_loopback_id) }} PHANTOM_RP_LB_ID2: {{ vxlan.underlay.multicast.underlay_backup_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_backup_rp_loopback_id) }} -{% if rp_count == 4 %} +{% if vxlan.underlay.multicast.rendezvous_points | default(defaults.vxlan.underlay.multicast.rendezvous_points) == 4 %} PHANTOM_RP_LB_ID3: {{ vxlan.underlay.multicast.underlay_second_backup_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_second_backup_rp_loopback_id) }} PHANTOM_RP_LB_ID4: {{ vxlan.underlay.multicast.underlay_third_backup_rp_loopback_id | default(defaults.vxlan.underlay.multicast.underlay_third_backup_rp_loopback_id) }} {% endif %} {% endif %} -{% else %} -{% if not manual_underlay %} +{% elif (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay) | ansible.builtin.bool) %} +{% if not (vxlan.underlay.general.manual_underlay_allocation | default(defaults.vxlan.underlay.general.manual_underlay_allocation) | ansible.builtin.bool) %} IPv6_ANYCAST_RP_IP_RANGE: {{ vxlan.underlay.ipv6.underlay_rp_loopback_ip_range | default(defaults.vxlan.underlay.ipv6.underlay_rp_loopback_ip_range) }} {% endif %} IPv6_MULTICAST_GROUP_SUBNET: {{ vxlan.underlay.multicast.ipv6.group_subnet | default(defaults.vxlan.underlay.multicast.ipv6.group_subnet) }} {% endif %} {% endif %} -{% if vxlan.global.ebgp.layer2_vni_range.from is defined -%} -{% set l2_vni_start = vxlan.global.ebgp.layer2_vni_range.from -%} -{% if vxlan.global.ebgp.layer2_vni_range.to is defined -%} -{% set l2_vni_end = vxlan.global.ebgp.layer2_vni_range.to -%} -{% endif -%} -{% endif -%} -{% if l2_vni_start is defined and l2_vni_end is not defined -%} -{% set l2_vni_range = l2_vni_start -%} -{% elif l2_vni_start is defined and l2_vni_end is defined -%} -{% set l2_vni_range = l2_vni_start ~ '-' ~ l2_vni_end -%} -{% else -%} -{% set l2_vni_range = defaults.vxlan.global.ebgp.layer2_vni_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer2_vni_range.to -%} +{% endif %} +{% if vxlan.global.ebgp.layer2_vni_range.from is defined %} +{% set l2_vni_start = vxlan.global.ebgp.layer2_vni_range.from %} +{% if vxlan.global.ebgp.layer2_vni_range.to is defined %} +{% set l2_vni_end = vxlan.global.ebgp.layer2_vni_range.to %} +{% endif %} +{% endif %} +{% if l2_vni_start is defined and l2_vni_end is not defined %} +{% set l2_vni_range = l2_vni_start %} +{% elif l2_vni_start is defined and l2_vni_end is defined %} +{% set l2_vni_range = l2_vni_start ~ '-' ~ l2_vni_end %} +{% else %} +{% set l2_vni_range = defaults.vxlan.global.ebgp.layer2_vni_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer2_vni_range.to %} {% endif %} L2_SEGMENT_ID_RANGE: {{ l2_vni_range }} -{% if vxlan.global.ebgp.layer3_vni_range.from is defined -%} -{% set l3_vni_start = vxlan.global.ebgp.layer3_vni_range.from -%} -{% if vxlan.global.ebgp.layer3_vni_range.to is defined -%} -{% set l3_vni_end = vxlan.global.ebgp.layer3_vni_range.to -%} -{% endif -%} -{% endif -%} -{% if l3_vni_start is defined and l3_vni_end is not defined -%} -{% set l3_vni_range = l3_vni_start -%} -{% elif l3_vni_start is defined and l3_vni_end is defined -%} -{% set l3_vni_range = l3_vni_start ~ '-' ~ l3_vni_end -%} -{% else -%} -{% set l3_vni_range = defaults.vxlan.global.ebgp.layer3_vni_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer3_vni_range.to -%} +{% if vxlan.global.ebgp.layer3_vni_range.from is defined %} +{% set l3_vni_start = vxlan.global.ebgp.layer3_vni_range.from %} +{% if vxlan.global.ebgp.layer3_vni_range.to is defined %} +{% set l3_vni_end = vxlan.global.ebgp.layer3_vni_range.to %} +{% endif %} +{% endif %} +{% if l3_vni_start is defined and l3_vni_end is not defined %} +{% set l3_vni_range = l3_vni_start %} +{% elif l3_vni_start is defined and l3_vni_end is defined %} +{% set l3_vni_range = l3_vni_start ~ '-' ~ l3_vni_end %} +{% else %} +{% set l3_vni_range = defaults.vxlan.global.ebgp.layer3_vni_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer3_vni_range.to %} {% endif %} L3_PARTITION_ID_RANGE: {{ l3_vni_range }} -{% if vxlan.global.ebgp.layer2_vlan_range.from is defined -%} -{% set l2_vlan_start = vxlan.global.ebgp.layer2_vlan_range.from -%} -{% if vxlan.global.ebgp.layer2_vlan_range.to is defined -%} -{% set l2_vlan_end = vxlan.global.ebgp.layer2_vlan_range.to -%} -{% endif -%} -{% endif -%} -{% if l2_vlan_start is defined and l2_vlan_end is not defined -%} -{% set l2_vlan_range = l2_vlan_start -%} -{% elif l2_vlan_start is defined and l2_vlan_end is defined -%} -{% set l2_vlan_range = l2_vlan_start ~ '-' ~ l2_vlan_end -%} -{% else -%} -{% set l2_vlan_range = defaults.vxlan.global.ebgp.layer2_vlan_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer2_vlan_range.to -%} +{% if vxlan.global.ebgp.layer2_vlan_range.from is defined %} +{% set l2_vlan_start = vxlan.global.ebgp.layer2_vlan_range.from %} +{% if vxlan.global.ebgp.layer2_vlan_range.to is defined %} +{% set l2_vlan_end = vxlan.global.ebgp.layer2_vlan_range.to %} +{% endif %} +{% endif %} +{% if l2_vlan_start is defined and l2_vlan_end is not defined %} +{% set l2_vlan_range = l2_vlan_start %} +{% elif l2_vlan_start is defined and l2_vlan_end is defined %} +{% set l2_vlan_range = l2_vlan_start ~ '-' ~ l2_vlan_end %} +{% else %} +{% set l2_vlan_range = defaults.vxlan.global.ebgp.layer2_vlan_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer2_vlan_range.to %} {% endif %} NETWORK_VLAN_RANGE: {{ l2_vlan_range }} -{% if vxlan.global.ebgp.layer3_vlan_range.from is defined -%} -{% set l3_vlan_start = vxlan.global.ebgp.layer3_vlan_range.from -%} -{% if vxlan.global.ebgp.layer3_vlan_range.to is defined -%} -{% set l3_vlan_end = vxlan.global.ebgp.layer3_vlan_range.to -%} -{% endif -%} -{% endif -%} -{% if l3_vlan_start is defined and l3_vlan_end is not defined -%} -{% set l3_vlan_range = l3_vlan_start -%} -{% elif l3_vlan_start is defined and l3_vlan_end is defined -%} -{% set l3_vlan_range = l3_vlan_start ~ '-' ~ l3_vlan_end -%} -{% else -%} -{% set l3_vlan_range = defaults.vxlan.global.ebgp.layer3_vlan_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer3_vlan_range.to -%} +{% if vxlan.global.ebgp.layer3_vlan_range.from is defined %} +{% set l3_vlan_start = vxlan.global.ebgp.layer3_vlan_range.from %} +{% if vxlan.global.ebgp.layer3_vlan_range.to is defined %} +{% set l3_vlan_end = vxlan.global.ebgp.layer3_vlan_range.to %} +{% endif %} +{% endif %} +{% if l3_vlan_start is defined and l3_vlan_end is not defined %} +{% set l3_vlan_range = l3_vlan_start %} +{% elif l3_vlan_start is defined and l3_vlan_end is defined %} +{% set l3_vlan_range = l3_vlan_start ~ '-' ~ l3_vlan_end %} +{% else %} +{% set l3_vlan_range = defaults.vxlan.global.ebgp.layer3_vlan_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer3_vlan_range.to %} {% endif %} VRF_VLAN_RANGE: {{ l3_vlan_range }} From 8417f959cbef8efddd8d83134414bc3ed7046d33 Mon Sep 17 00:00:00 2001 From: "Slawomir Kaszlikowski (skaszlik)" Date: Tue, 18 Nov 2025 15:12:27 +0100 Subject: [PATCH 07/14] Add ANYCAST_RP_IP_RANGE to eBGP VXLAN EVPN configuration --- .../ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 index 24732dfb8..0c8af313c 100644 --- a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 +++ b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 @@ -18,6 +18,7 @@ {% if not (vxlan.underlay.general.manual_underlay_allocation | default(defaults.vxlan.underlay.general.manual_underlay_allocation) | ansible.builtin.bool) %} {% if not (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay) | ansible.builtin.bool) %} LOOPBACK1_IP_RANGE: {{ vxlan.underlay.ipv4.underlay_vtep_loopback_ip_range | default(defaults.vxlan.underlay.ipv4.underlay_vtep_loopback_ip_range) }} + ANYCAST_RP_IP_RANGE: {{ vxlan.underlay.ipv4.underlay_rp_loopback_ip_range | default(defaults.vxlan.underlay.ipv4.underlay_rp_loopback_ip_range) }} {% if (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay) | ansible.builtin.bool) %} LOOPBACK1_IPV6_RANGE: {{ vxlan.underlay.ipv6.underlay_vtep_loopback_ip_range | default(defaults.vxlan.underlay.ipv6.underlay_vtep_loopback_ip_range) }} {% endif %} @@ -35,9 +36,6 @@ ENABLE_TRMv6: {{ vxlan.underlay.multicast.ipv6.trmv6_enable | default(defaults.vxlan.underlay.multicast.ipv6.trmv6_enable) | title }} {% endif %} {% if not (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay) | ansible.builtin.bool) %} -{% if not (vxlan.underlay.general.manual_underlay_allocation | default(defaults.vxlan.underlay.general.manual_underlay_allocation) | ansible.builtin.bool) %} - ANYCAST_RP_IP_RANGE: {{ vxlan.underlay.ipv4.underlay_rp_loopback_ip_range | default(defaults.vxlan.underlay.ipv4.underlay_rp_loopback_ip_range) }} -{% endif %} MULTICAST_GROUP_SUBNET: {{ vxlan.underlay.multicast.ipv4.group_subnet | default(defaults.vxlan.underlay.multicast.ipv4.group_subnet) }} {# {% if (vxlan.underlay.multicast.ipv4.trm_enable | default(defaults.vxlan.underlay.multicast.ipv4.trm_enable) | ansible.builtin.bool) %} #} {# L3VNI_MCAST_GROUP: {{ vxlan.underlay.multicast.ipv4.trm_default_group | default(defaults.vxlan.underlay.multicast.ipv4.trm_default_group) }} #} From 8efd1f957b7f00d629b8f234576c4aaded74894f Mon Sep 17 00:00:00 2001 From: "Slawomir Kaszlikowski (skaszlik)" Date: Tue, 18 Nov 2025 16:15:32 +0100 Subject: [PATCH 08/14] Enforce matching Port-channel ID with vPC ID to prevent configuration mismatches --- .../305_topology_switch_interfaces_vpc.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/roles/validate/files/rules/common/305_topology_switch_interfaces_vpc.py b/roles/validate/files/rules/common/305_topology_switch_interfaces_vpc.py index cf39d6b33..98b5f78b9 100644 --- a/roles/validate/files/rules/common/305_topology_switch_interfaces_vpc.py +++ b/roles/validate/files/rules/common/305_topology_switch_interfaces_vpc.py @@ -53,6 +53,24 @@ def match(cls, data_model): ) return results + # Enforce Port-channel ID matches vPC ID to avoid mismatched configurations + port_channel_match = re.fullmatch( + r"Port-channel(\d+)", interface_name + ) + if port_channel_match: + port_channel_id = port_channel_match.group(1) + try: + vpc_id_int_value = int(vpc_id) + except (TypeError, ValueError): + results.append( + f"Switch {switch_name} interface {interface_name} has non-numeric vPC id {vpc_id}; use an integer matching the Port-channel ID." + ) + continue + if int(port_channel_id) != vpc_id_int_value: + results.append( + f"Switch {switch_name} interface {interface_name} uses vPC id {vpc_id} but Port-channel ID {port_channel_id}; these values must match." + ) + # Check if vPC id is referenced by more than 1 Port-channel on the switch if vpc_id in vpc_ids: results.append( From dd318e1bac8d961bb46ec9d79b42ff1e0a8c2450 Mon Sep 17 00:00:00 2001 From: "Slawomir Kaszlikowski (skaszlik)" Date: Tue, 18 Nov 2025 16:18:57 +0100 Subject: [PATCH 09/14] revert back changes - its not part of that issue --- .../ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 index 0c8af313c..1b8c96313 100644 --- a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 +++ b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 @@ -18,7 +18,6 @@ {% if not (vxlan.underlay.general.manual_underlay_allocation | default(defaults.vxlan.underlay.general.manual_underlay_allocation) | ansible.builtin.bool) %} {% if not (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay) | ansible.builtin.bool) %} LOOPBACK1_IP_RANGE: {{ vxlan.underlay.ipv4.underlay_vtep_loopback_ip_range | default(defaults.vxlan.underlay.ipv4.underlay_vtep_loopback_ip_range) }} - ANYCAST_RP_IP_RANGE: {{ vxlan.underlay.ipv4.underlay_rp_loopback_ip_range | default(defaults.vxlan.underlay.ipv4.underlay_rp_loopback_ip_range) }} {% if (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay) | ansible.builtin.bool) %} LOOPBACK1_IPV6_RANGE: {{ vxlan.underlay.ipv6.underlay_vtep_loopback_ip_range | default(defaults.vxlan.underlay.ipv6.underlay_vtep_loopback_ip_range) }} {% endif %} @@ -36,6 +35,9 @@ ENABLE_TRMv6: {{ vxlan.underlay.multicast.ipv6.trmv6_enable | default(defaults.vxlan.underlay.multicast.ipv6.trmv6_enable) | title }} {% endif %} {% if not (vxlan.underlay.general.enable_ipv6_underlay | default(defaults.vxlan.underlay.general.enable_ipv6_underlay) | ansible.builtin.bool) %} +{% if not (vxlan.underlay.general.manual_underlay_allocation | default(defaults.vxlan.underlay.general.manual_underlay_allocation) | ansible.builtin.bool) %} + ANYCAST_RP_IP_RANGE: {{ vxlan.underlay.ipv4.underlay_rp_loopback_ip_range | default(defaults.vxlan.underlay.ipv4.underlay_rp_loopback_ip_range) }} +{% endif %} MULTICAST_GROUP_SUBNET: {{ vxlan.underlay.multicast.ipv4.group_subnet | default(defaults.vxlan.underlay.multicast.ipv4.group_subnet) }} {# {% if (vxlan.underlay.multicast.ipv4.trm_enable | default(defaults.vxlan.underlay.multicast.ipv4.trm_enable) | ansible.builtin.bool) %} #} {# L3VNI_MCAST_GROUP: {{ vxlan.underlay.multicast.ipv4.trm_default_group | default(defaults.vxlan.underlay.multicast.ipv4.trm_default_group) }} #} @@ -115,4 +117,4 @@ {% else %} {% set l3_vlan_range = defaults.vxlan.global.ebgp.layer3_vlan_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer3_vlan_range.to %} {% endif %} - VRF_VLAN_RANGE: {{ l3_vlan_range }} + VRF_VLAN_RANGE: {{ l3_vlan_range }} \ No newline at end of file From a4def14fdc2e9e6311e62762f96c1ea181cf4a36 Mon Sep 17 00:00:00 2001 From: "Slawomir Kaszlikowski (skaszlik)" Date: Tue, 18 Nov 2025 16:19:31 +0100 Subject: [PATCH 10/14] add blank --- .../ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 index 1b8c96313..6586362e1 100644 --- a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 +++ b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 @@ -117,4 +117,5 @@ {% else %} {% set l3_vlan_range = defaults.vxlan.global.ebgp.layer3_vlan_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer3_vlan_range.to %} {% endif %} - VRF_VLAN_RANGE: {{ l3_vlan_range }} \ No newline at end of file + VRF_VLAN_RANGE: {{ l3_vlan_range }} + \ No newline at end of file From 031181dcf44a13e553a230c882a5a523934b3d13 Mon Sep 17 00:00:00 2001 From: "Slawomir Kaszlikowski (skaszlik)" Date: Tue, 18 Nov 2025 16:20:40 +0100 Subject: [PATCH 11/14] Remove unnecessary newline before VRF_VLAN_RANGE in eBGP VXLAN EVPN template --- .../ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 index 6586362e1..1b8c96313 100644 --- a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 +++ b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 @@ -117,5 +117,4 @@ {% else %} {% set l3_vlan_range = defaults.vxlan.global.ebgp.layer3_vlan_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer3_vlan_range.to %} {% endif %} - VRF_VLAN_RANGE: {{ l3_vlan_range }} - \ No newline at end of file + VRF_VLAN_RANGE: {{ l3_vlan_range }} \ No newline at end of file From ee263204d614618803b71c6387cb8a8a44b8866f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C5=82awomir=20Kaszlikowski?= Date: Tue, 18 Nov 2025 16:51:22 +0100 Subject: [PATCH 12/14] Update ebgp_vxlan_fabric_evpn.j2 --- .../ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 index 1b8c96313..24732dfb8 100644 --- a/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 +++ b/roles/dtc/common/templates/ndfc_fabric/ebgp_vxlan_fabric/evpn/ebgp_vxlan_fabric_evpn.j2 @@ -117,4 +117,4 @@ {% else %} {% set l3_vlan_range = defaults.vxlan.global.ebgp.layer3_vlan_range.from ~ '-' ~ defaults.vxlan.global.ebgp.layer3_vlan_range.to %} {% endif %} - VRF_VLAN_RANGE: {{ l3_vlan_range }} \ No newline at end of file + VRF_VLAN_RANGE: {{ l3_vlan_range }} From 2fffca788619e5f88c258780bb6358ee8e790244 Mon Sep 17 00:00:00 2001 From: "Slawomir Kaszlikowski (skaszlik)" Date: Wed, 19 Nov 2025 09:24:56 +0100 Subject: [PATCH 13/14] Refactor vPC ID validation to simplify comparison logic and ensure consistency with Port-channel ID --- .../rules/common/305_topology_switch_interfaces_vpc.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/roles/validate/files/rules/common/305_topology_switch_interfaces_vpc.py b/roles/validate/files/rules/common/305_topology_switch_interfaces_vpc.py index 98b5f78b9..d9b8f7129 100644 --- a/roles/validate/files/rules/common/305_topology_switch_interfaces_vpc.py +++ b/roles/validate/files/rules/common/305_topology_switch_interfaces_vpc.py @@ -59,14 +59,8 @@ def match(cls, data_model): ) if port_channel_match: port_channel_id = port_channel_match.group(1) - try: - vpc_id_int_value = int(vpc_id) - except (TypeError, ValueError): - results.append( - f"Switch {switch_name} interface {interface_name} has non-numeric vPC id {vpc_id}; use an integer matching the Port-channel ID." - ) - continue - if int(port_channel_id) != vpc_id_int_value: + + if int(port_channel_id) != int(vpc_id): results.append( f"Switch {switch_name} interface {interface_name} uses vPC id {vpc_id} but Port-channel ID {port_channel_id}; these values must match." ) From 2448db55eabefe3b31f00feaa105f83afff02ebc Mon Sep 17 00:00:00 2001 From: "Slawomir Kaszlikowski (skaszlik)" Date: Wed, 19 Nov 2025 09:29:58 +0100 Subject: [PATCH 14/14] Fix vPC ID mismatch message formatting in validation rule --- .../files/rules/common/305_topology_switch_interfaces_vpc.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/roles/validate/files/rules/common/305_topology_switch_interfaces_vpc.py b/roles/validate/files/rules/common/305_topology_switch_interfaces_vpc.py index d9b8f7129..c6ad2ed49 100644 --- a/roles/validate/files/rules/common/305_topology_switch_interfaces_vpc.py +++ b/roles/validate/files/rules/common/305_topology_switch_interfaces_vpc.py @@ -59,10 +59,11 @@ def match(cls, data_model): ) if port_channel_match: port_channel_id = port_channel_match.group(1) - + if int(port_channel_id) != int(vpc_id): results.append( - f"Switch {switch_name} interface {interface_name} uses vPC id {vpc_id} but Port-channel ID {port_channel_id}; these values must match." + f"Switch {switch_name} interface {interface_name} uses vPC id {vpc_id}" + "but Port-channel ID {port_channel_id}; these values must match." ) # Check if vPC id is referenced by more than 1 Port-channel on the switch