From a6e90ce6bcd5239f881ce83a11ec2a767addbaf1 Mon Sep 17 00:00:00 2001 From: Blake Becton <238314145+tech-of-all-trades@users.noreply.github.com> Date: Wed, 19 Nov 2025 15:34:53 -0500 Subject: [PATCH 1/2] feat: Add IPv6 PIM module with VRF support and examples Add Terraform module support for VRF-aware IPv6 PIM configuration and interface-level IPv6 PIM control with comprehensive TRM deployment examples. New Resources: - iosxe_ipv6_pim: Global/VRF IPv6 PIM RP configuration - iosxe_interface_ipv6_pim: Interface IPv6 PIM (Ethernet, Loopback, VLAN, Port-channel) Features: - Per-VRF RP addresses with group ranges (e.g., ff70::/12) - Interface PIM enablement - Bidirectional PIM support Example (`./examples/ipv6_pim/`): - TRM scenario with 2 VRFs and isolated multicast domains - 3 RP Loopbacks, 3 multicast VLANs - Different group ranges per VRF CLI Support: - `ipv6 pim [vrf ] rp-address ` - `ipv6 pim` (interface-level) Files: - iosxe_ipv6_pim.tf - iosxe_interfaces.tf - examples/ipv6_pim/.terraform-docs.yml - examples/ipv6_pim/README.md - examples/ipv6_pim/versions.tf - examples/ipv6_pim/main.tf - examples/ipv6_pim/ipv6_pim.nac.yaml - .pre-commit-config.yaml (terraform-docs hook) - README.md (auto-generated) --- .pre-commit-config.yaml | 2 + README.md | 5 + examples/ipv6_pim/.terraform-docs.yml | 57 +++++++++ examples/ipv6_pim/README.md | 167 ++++++++++++++++++++++++++ examples/ipv6_pim/ipv6_pim.nac.yaml | 113 +++++++++++++++++ examples/ipv6_pim/main.tf | 7 ++ examples/ipv6_pim/versions.tf | 11 ++ iosxe_interfaces.tf | 84 +++++++++++++ iosxe_ipv6_pim.tf | 20 +++ 9 files changed, 466 insertions(+) create mode 100644 examples/ipv6_pim/.terraform-docs.yml create mode 100644 examples/ipv6_pim/README.md create mode 100644 examples/ipv6_pim/ipv6_pim.nac.yaml create mode 100644 examples/ipv6_pim/main.tf create mode 100644 examples/ipv6_pim/versions.tf create mode 100644 iosxe_ipv6_pim.tf diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 348ff3a..41136ea 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,5 +17,7 @@ repos: args: ["./modules/model/examples/model_file"] - id: terraform-docs-system args: ["./examples/system"] + - id: terraform-docs-system + args: ["./examples/ipv6_pim"] - id: terraform-docs-system args: ["."] diff --git a/README.md b/README.md index 94121fa..6d7b27c 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,10 @@ module "iosxe" { | [iosxe_flow_monitor.flow_monitor](https://registry.terraform.io/providers/CiscoDevNet/iosxe/0.10.2/docs/resources/flow_monitor) | resource | | [iosxe_flow_record.flow_record](https://registry.terraform.io/providers/CiscoDevNet/iosxe/0.10.2/docs/resources/flow_record) | resource | | [iosxe_interface_ethernet.ethernet](https://registry.terraform.io/providers/CiscoDevNet/iosxe/0.10.2/docs/resources/interface_ethernet) | resource | +| [iosxe_interface_ipv6_pim.ethernet_ipv6_pim](https://registry.terraform.io/providers/CiscoDevNet/iosxe/0.10.2/docs/resources/interface_ipv6_pim) | resource | +| [iosxe_interface_ipv6_pim.loopback_ipv6_pim](https://registry.terraform.io/providers/CiscoDevNet/iosxe/0.10.2/docs/resources/interface_ipv6_pim) | resource | +| [iosxe_interface_ipv6_pim.port_channel_ipv6_pim](https://registry.terraform.io/providers/CiscoDevNet/iosxe/0.10.2/docs/resources/interface_ipv6_pim) | resource | +| [iosxe_interface_ipv6_pim.vlan_ipv6_pim](https://registry.terraform.io/providers/CiscoDevNet/iosxe/0.10.2/docs/resources/interface_ipv6_pim) | resource | | [iosxe_interface_loopback.loopback](https://registry.terraform.io/providers/CiscoDevNet/iosxe/0.10.2/docs/resources/interface_loopback) | resource | | [iosxe_interface_mpls.ethernet_mpls](https://registry.terraform.io/providers/CiscoDevNet/iosxe/0.10.2/docs/resources/interface_mpls) | resource | | [iosxe_interface_mpls.loopback_mpls](https://registry.terraform.io/providers/CiscoDevNet/iosxe/0.10.2/docs/resources/interface_mpls) | resource | @@ -154,6 +158,7 @@ module "iosxe" { | [iosxe_interface_switchport.ethernet_switchport](https://registry.terraform.io/providers/CiscoDevNet/iosxe/0.10.2/docs/resources/interface_switchport) | resource | | [iosxe_interface_switchport.port_channel_switchport](https://registry.terraform.io/providers/CiscoDevNet/iosxe/0.10.2/docs/resources/interface_switchport) | resource | | [iosxe_interface_vlan.vlan](https://registry.terraform.io/providers/CiscoDevNet/iosxe/0.10.2/docs/resources/interface_vlan) | resource | +| [iosxe_ipv6_pim.ipv6_pim](https://registry.terraform.io/providers/CiscoDevNet/iosxe/0.10.2/docs/resources/ipv6_pim) | resource | | [iosxe_license.license](https://registry.terraform.io/providers/CiscoDevNet/iosxe/0.10.2/docs/resources/license) | resource | | [iosxe_line.line](https://registry.terraform.io/providers/CiscoDevNet/iosxe/0.10.2/docs/resources/line) | resource | | [iosxe_lldp.lldp](https://registry.terraform.io/providers/CiscoDevNet/iosxe/0.10.2/docs/resources/lldp) | resource | diff --git a/examples/ipv6_pim/.terraform-docs.yml b/examples/ipv6_pim/.terraform-docs.yml new file mode 100644 index 0000000..1ec4c71 --- /dev/null +++ b/examples/ipv6_pim/.terraform-docs.yml @@ -0,0 +1,57 @@ +version: ">= 0.14.0" + +formatter: markdown table + +content: |- + # IPv6 PIM Configuration Example + + This example demonstrates VRF-aware IPv6 PIM configuration for TRM (Tenant Routed Multicast) deployments. + + ## Features + + - Global IPv6 PIM RP configuration + - VRF-aware IPv6 PIM with isolated multicast domains + - Interface-level IPv6 PIM on Loopbacks and VLANs + - Multiple VRFs with independent RP addresses + - Different multicast group ranges per VRF + + ## Usage + + To run this example you need to execute: + + ```bash + $ terraform init + $ terraform plan + $ terraform apply + ``` + + Note that this example will create resources. Resources can be destroyed with `terraform destroy`. + + ## Configuration + + #### `ipv6_pim.nac.yaml` + + ```yaml + {{ include "./ipv6_pim.nac.yaml" }} + ``` + + #### `main.tf` + + ```hcl + {{ include "./main.tf" }} + ``` + + ## Scenario + + This configuration demonstrates a complete TRM deployment with: + - 2 VRFs (BLUE, GREEN) with isolated multicast domains + - Global RP: 2001:db8::100 with group range ff70::/12 + - VRF BLUE RP: 2001:db8:1::100 with group range ff71::/12 + - VRF GREEN RP: 2001:db8:2::100 with group range ff72::/12 + - 3 RP Loopbacks with high DR priority + - 3 Multicast VLANs with per-VRF isolation + +output: + file: README.md + mode: replace + diff --git a/examples/ipv6_pim/README.md b/examples/ipv6_pim/README.md new file mode 100644 index 0000000..289d624 --- /dev/null +++ b/examples/ipv6_pim/README.md @@ -0,0 +1,167 @@ + +# IPv6 PIM Configuration Example + +This example demonstrates VRF-aware IPv6 PIM configuration for TRM (Tenant Routed Multicast) deployments. + +## Features + +- Global IPv6 PIM RP configuration +- VRF-aware IPv6 PIM with isolated multicast domains +- Interface-level IPv6 PIM on Loopbacks and VLANs +- Multiple VRFs with independent RP addresses +- Different multicast group ranges per VRF + +## Usage + +To run this example you need to execute: + +```bash +$ terraform init +$ terraform plan +$ terraform apply +``` + +Note that this example will create resources. Resources can be destroyed with `terraform destroy`. + +## Configuration + +#### `ipv6_pim.nac.yaml` + +```yaml +--- +iosxe: + devices: + - name: Router1 + host: 10.1.1.1 + configuration: + system: + hostname: Router1 + ipv6_unicast_routing: true + + # VRF Configuration + vrfs: + - name: BLUE + address_family_ipv6: + enable: true + - name: GREEN + address_family_ipv6: + enable: true + + # Global and VRF-aware IPv6 PIM Configuration + ipv6_pim: + # Global IPv6 PIM RP + rp_address: 2001:db8::100 + rp_address_access_list: ff70::/12 + rp_address_bidir: false + + # Per-VRF IPv6 PIM RP Configuration + vrfs: + - vrf: BLUE + rp_address: 2001:db8:1::100 + rp_address_access_list: ff71::/12 + rp_address_bidir: false + + - vrf: GREEN + rp_address: 2001:db8:2::100 + rp_address_access_list: ff72::/12 + rp_address_bidir: false + + # Interface Configuration + interfaces: + loopbacks: + # Global RP Loopback + - id: 100 + description: "IPv6 PIM RP - Global" + ipv6: + enable: true + addresses: + - prefix: 2001:db8::100/128 + pim: + pim: true + dr_priority: 100 + + # VRF BLUE RP Loopback + - id: 101 + description: "IPv6 PIM RP - VRF BLUE" + vrf_forwarding: BLUE + ipv6: + enable: true + addresses: + - prefix: 2001:db8:1::100/128 + pim: + pim: true + dr_priority: 100 + + # VRF GREEN RP Loopback + - id: 102 + description: "IPv6 PIM RP - VRF GREEN" + vrf_forwarding: GREEN + ipv6: + enable: true + addresses: + - prefix: 2001:db8:2::100/128 + pim: + pim: true + dr_priority: 100 + + vlans: + # Global VLAN with IPv6 PIM + - id: 10 + description: "IPv6 Multicast VLAN - Global" + ipv6: + enable: true + addresses: + - prefix: 2001:db8:10::1/64 + pim: + pim: true + bfd: false + bsr_border: false + dr_priority: 10 + + # VRF BLUE VLAN with IPv6 PIM + - id: 20 + description: "IPv6 Multicast VLAN - VRF BLUE" + vrf_forwarding: BLUE + ipv6: + enable: true + addresses: + - prefix: 2001:db8:20::1/64 + pim: + pim: true + dr_priority: 20 + + # VRF GREEN VLAN with IPv6 PIM + - id: 30 + description: "IPv6 Multicast VLAN - VRF GREEN" + vrf_forwarding: GREEN + ipv6: + enable: true + addresses: + - prefix: 2001:db8:30::1/64 + pim: + pim: true + dr_priority: 30 +``` + +#### `main.tf` + +```hcl +module "iosxe" { + source = "netascode/nac-iosxe/iosxe" + version = ">= 0.1.0" + + yaml_files = ["ipv6_pim.nac.yaml"] +} + +``` + +## Scenario + +This configuration demonstrates a complete TRM deployment with: +- 2 VRFs (BLUE, GREEN) with isolated multicast domains +- Global RP: 2001:db8::100 with group range ff70::/12 +- VRF BLUE RP: 2001:db8:1::100 with group range ff71::/12 +- VRF GREEN RP: 2001:db8:2::100 with group range ff72::/12 +- 3 RP Loopbacks with high DR priority +- 3 Multicast VLANs with per-VRF isolation + \ No newline at end of file diff --git a/examples/ipv6_pim/ipv6_pim.nac.yaml b/examples/ipv6_pim/ipv6_pim.nac.yaml new file mode 100644 index 0000000..0eef8ab --- /dev/null +++ b/examples/ipv6_pim/ipv6_pim.nac.yaml @@ -0,0 +1,113 @@ +--- +iosxe: + devices: + - name: Router1 + host: 10.1.1.1 + configuration: + system: + hostname: Router1 + ipv6_unicast_routing: true + + # VRF Configuration + vrfs: + - name: BLUE + address_family_ipv6: + enable: true + - name: GREEN + address_family_ipv6: + enable: true + + # Global and VRF-aware IPv6 PIM Configuration + ipv6_pim: + # Global IPv6 PIM RP + rp_address: 2001:db8::100 + rp_address_access_list: ff70::/12 + rp_address_bidir: false + + # Per-VRF IPv6 PIM RP Configuration + vrfs: + - vrf: BLUE + rp_address: 2001:db8:1::100 + rp_address_access_list: ff71::/12 + rp_address_bidir: false + + - vrf: GREEN + rp_address: 2001:db8:2::100 + rp_address_access_list: ff72::/12 + rp_address_bidir: false + + # Interface Configuration + interfaces: + loopbacks: + # Global RP Loopback + - id: 100 + description: "IPv6 PIM RP - Global" + ipv6: + enable: true + addresses: + - prefix: 2001:db8::100/128 + pim: + pim: true + dr_priority: 100 + + # VRF BLUE RP Loopback + - id: 101 + description: "IPv6 PIM RP - VRF BLUE" + vrf_forwarding: BLUE + ipv6: + enable: true + addresses: + - prefix: 2001:db8:1::100/128 + pim: + pim: true + dr_priority: 100 + + # VRF GREEN RP Loopback + - id: 102 + description: "IPv6 PIM RP - VRF GREEN" + vrf_forwarding: GREEN + ipv6: + enable: true + addresses: + - prefix: 2001:db8:2::100/128 + pim: + pim: true + dr_priority: 100 + + vlans: + # Global VLAN with IPv6 PIM + - id: 10 + description: "IPv6 Multicast VLAN - Global" + ipv6: + enable: true + addresses: + - prefix: 2001:db8:10::1/64 + pim: + pim: true + bfd: false + bsr_border: false + dr_priority: 10 + + # VRF BLUE VLAN with IPv6 PIM + - id: 20 + description: "IPv6 Multicast VLAN - VRF BLUE" + vrf_forwarding: BLUE + ipv6: + enable: true + addresses: + - prefix: 2001:db8:20::1/64 + pim: + pim: true + dr_priority: 20 + + # VRF GREEN VLAN with IPv6 PIM + - id: 30 + description: "IPv6 Multicast VLAN - VRF GREEN" + vrf_forwarding: GREEN + ipv6: + enable: true + addresses: + - prefix: 2001:db8:30::1/64 + pim: + pim: true + dr_priority: 30 diff --git a/examples/ipv6_pim/main.tf b/examples/ipv6_pim/main.tf new file mode 100644 index 0000000..c148b02 --- /dev/null +++ b/examples/ipv6_pim/main.tf @@ -0,0 +1,7 @@ +module "iosxe" { + source = "netascode/nac-iosxe/iosxe" + version = ">= 0.1.0" + + yaml_files = ["ipv6_pim.nac.yaml"] +} + diff --git a/examples/ipv6_pim/versions.tf b/examples/ipv6_pim/versions.tf new file mode 100644 index 0000000..a38c1e5 --- /dev/null +++ b/examples/ipv6_pim/versions.tf @@ -0,0 +1,11 @@ +terraform { + required_version = ">= 1.8.0" + + required_providers { + iosxe = { + source = "CiscoDevNet/iosxe" + version = ">= 0.10.2" + } + } +} + diff --git a/iosxe_interfaces.tf b/iosxe_interfaces.tf index 5925bae..130ad69 100644 --- a/iosxe_interfaces.tf +++ b/iosxe_interfaces.tf @@ -181,6 +181,11 @@ locals { pim_border = try(int.pim.border, local.defaults.iosxe.devices.configuration.interfaces.ethernets.pim.border, null) pim_bsr_border = try(int.pim.bsr_border, local.defaults.iosxe.devices.configuration.interfaces.ethernets.pim.bsr_border, null) pim_dr_priority = try(int.pim.dr_priority, local.defaults.iosxe.devices.configuration.interfaces.ethernets.pim.dr_priority, null) + ipv6_pim = try(int.ipv6.pim, null) != null ? true : false + ipv6_pim_pim = try(int.ipv6.pim.pim, local.defaults.iosxe.devices.configuration.interfaces.ethernets.ipv6.pim.pim, null) + ipv6_pim_bfd = try(int.ipv6.pim.bfd, local.defaults.iosxe.devices.configuration.interfaces.ethernets.ipv6.pim.bfd, null) + ipv6_pim_bsr_border = try(int.ipv6.pim.bsr_border, local.defaults.iosxe.devices.configuration.interfaces.ethernets.ipv6.pim.bsr_border, null) + ipv6_pim_dr_priority = try(int.ipv6.pim.dr_priority, local.defaults.iosxe.devices.configuration.interfaces.ethernets.ipv6.pim.dr_priority, null) authentication_periodic = try(int.network_access_control.authentication_periodic, local.defaults.iosxe.devices.configuration.interfaces.ethernets.network_access_control.authentication_periodic, null) authentication_timer_reauthenticate = try(int.network_access_control.authentication_timer_reauthenticate, local.defaults.iosxe.devices.configuration.interfaces.ethernets.network_access_control.authentication_timer_reauthenticate, null) authentication_timer_reauthenticate_server = try(int.network_access_control.authentication_timer_reauthenticate_server, local.defaults.iosxe.devices.configuration.interfaces.ethernets.network_access_control.authentication_timer_reauthenticate_server, null) @@ -437,6 +442,22 @@ resource "iosxe_interface_pim" "ethernet_pim" { ] } +resource "iosxe_interface_ipv6_pim" "ethernet_ipv6_pim" { + for_each = { for v in local.interfaces_ethernets : v.key => v if v.ipv6_pim } + + device = each.value.device + type = each.value.type + name = each.value.id + pim = each.value.ipv6_pim_pim + bfd = each.value.ipv6_pim_bfd + bsr_border = each.value.ipv6_pim_bsr_border + dr_priority = each.value.ipv6_pim_dr_priority + + depends_on = [ + iosxe_interface_ethernet.ethernet + ] +} + ##### LOOPBACKS ##### locals { @@ -517,6 +538,11 @@ locals { pim_border = try(int.pim.border, local.defaults.iosxe.devices.configuration.interfaces.loopbacks.pim.border, null) pim_bsr_border = try(int.pim.bsr_border, local.defaults.iosxe.devices.configuration.interfaces.loopbacks.pim.bsr_border, null) pim_dr_priority = try(int.pim.dr_priority, local.defaults.iosxe.devices.configuration.interfaces.loopbacks.pim.dr_priority, null) + ipv6_pim = try(int.ipv6.pim, null) != null ? true : false + ipv6_pim_pim = try(int.ipv6.pim.pim, local.defaults.iosxe.devices.configuration.interfaces.loopbacks.ipv6.pim.pim, null) + ipv6_pim_bfd = try(int.ipv6.pim.bfd, local.defaults.iosxe.devices.configuration.interfaces.loopbacks.ipv6.pim.bfd, null) + ipv6_pim_bsr_border = try(int.ipv6.pim.bsr_border, local.defaults.iosxe.devices.configuration.interfaces.loopbacks.ipv6.pim.bsr_border, null) + ipv6_pim_dr_priority = try(int.ipv6.pim.dr_priority, local.defaults.iosxe.devices.configuration.interfaces.loopbacks.ipv6.pim.dr_priority, null) } ] ]) @@ -635,6 +661,22 @@ resource "iosxe_interface_pim" "loopback_pim" { ] } +resource "iosxe_interface_ipv6_pim" "loopback_ipv6_pim" { + for_each = { for v in local.interfaces_loopbacks : v.key => v if v.ipv6_pim } + + device = each.value.device + type = "Loopback" + name = each.value.id + pim = each.value.ipv6_pim_pim + bfd = each.value.ipv6_pim_bfd + bsr_border = each.value.ipv6_pim_bsr_border + dr_priority = each.value.ipv6_pim_dr_priority + + depends_on = [ + iosxe_interface_loopback.loopback + ] +} + ####### VLANS ####### locals { @@ -729,6 +771,11 @@ locals { pim_border = try(int.pim.border, local.defaults.iosxe.devices.configuration.interfaces.vlans.pim.border, null) pim_bsr_border = try(int.pim.bsr_border, local.defaults.iosxe.devices.configuration.interfaces.vlans.pim.bsr_border, null) pim_dr_priority = try(int.pim.dr_priority, local.defaults.iosxe.devices.configuration.interfaces.vlans.pim.dr_priority, null) + ipv6_pim = try(int.ipv6.pim, null) != null ? true : false + ipv6_pim_pim = try(int.ipv6.pim.pim, local.defaults.iosxe.devices.configuration.interfaces.vlans.ipv6.pim.pim, null) + ipv6_pim_bfd = try(int.ipv6.pim.bfd, local.defaults.iosxe.devices.configuration.interfaces.vlans.ipv6.pim.bfd, null) + ipv6_pim_bsr_border = try(int.ipv6.pim.bsr_border, local.defaults.iosxe.devices.configuration.interfaces.vlans.ipv6.pim.bsr_border, null) + ipv6_pim_dr_priority = try(int.ipv6.pim.dr_priority, local.defaults.iosxe.devices.configuration.interfaces.vlans.ipv6.pim.dr_priority, null) } ] ]) @@ -860,6 +907,22 @@ resource "iosxe_interface_pim" "vlan_pim" { ] } +resource "iosxe_interface_ipv6_pim" "vlan_ipv6_pim" { + for_each = { for v in local.interfaces_vlans : v.key => v if v.ipv6_pim } + + device = each.value.device + type = "Vlan" + name = each.value.id + pim = each.value.ipv6_pim_pim + bfd = each.value.ipv6_pim_bfd + bsr_border = each.value.ipv6_pim_bsr_border + dr_priority = each.value.ipv6_pim_dr_priority + + depends_on = [ + iosxe_interface_vlan.vlan + ] +} + ##### PORT-CHANNELS ##### locals { @@ -988,6 +1051,11 @@ locals { pim_border = try(int.pim.border, local.defaults.iosxe.devices.configuration.interfaces.port_channels.pim.border, null) pim_bsr_border = try(int.pim.bsr_border, local.defaults.iosxe.devices.configuration.interfaces.port_channels.pim.bsr_border, null) pim_dr_priority = try(int.pim.dr_priority, local.defaults.iosxe.devices.configuration.interfaces.port_channels.pim.dr_priority, null) + ipv6_pim = try(int.ipv6.pim, null) != null ? true : false + ipv6_pim_pim = try(int.ipv6.pim.pim, local.defaults.iosxe.devices.configuration.interfaces.port_channels.ipv6.pim.pim, null) + ipv6_pim_bfd = try(int.ipv6.pim.bfd, local.defaults.iosxe.devices.configuration.interfaces.port_channels.ipv6.pim.bfd, null) + ipv6_pim_bsr_border = try(int.ipv6.pim.bsr_border, local.defaults.iosxe.devices.configuration.interfaces.port_channels.ipv6.pim.bsr_border, null) + ipv6_pim_dr_priority = try(int.ipv6.pim.dr_priority, local.defaults.iosxe.devices.configuration.interfaces.port_channels.ipv6.pim.dr_priority, null) auto_qos_classify = try(int.auto_qos.classify, local.defaults.iosxe.devices.configuration.interfaces.port_channels.auto_qos.classify, null) auto_qos_classify_police = try(int.auto_qos.classify_police, local.defaults.iosxe.devices.configuration.interfaces.port_channels.auto_qos.classify_police, null) auto_qos_trust = try(int.auto_qos.trust, local.defaults.iosxe.devices.configuration.interfaces.port_channels.auto_qos.trust, null) @@ -1172,6 +1240,22 @@ resource "iosxe_interface_pim" "port_channel_pim" { ] } +resource "iosxe_interface_ipv6_pim" "port_channel_ipv6_pim" { + for_each = { for v in local.interfaces_port_channels : v.key => v if v.ipv6_pim } + + device = each.value.device + type = "Port-channel" + name = each.value.name + pim = each.value.ipv6_pim_pim + bfd = each.value.ipv6_pim_bfd + bsr_border = each.value.ipv6_pim_bsr_border + dr_priority = each.value.ipv6_pim_dr_priority + + depends_on = [ + iosxe_interface_port_channel.port_channel + ] +} + ##### PORT-CHANNEL SUBINTERFACES ##### locals { diff --git a/iosxe_ipv6_pim.tf b/iosxe_ipv6_pim.tf new file mode 100644 index 0000000..c1a7221 --- /dev/null +++ b/iosxe_ipv6_pim.tf @@ -0,0 +1,20 @@ +resource "iosxe_ipv6_pim" "ipv6_pim" { + for_each = { for device in local.devices : device.name => device if try(local.device_config[device.name].ipv6_pim, null) != null } + device = each.value.name + + rp_address = try(local.device_config[each.value.name].ipv6_pim.rp_address, local.defaults.iosxe.configuration.ipv6_pim.rp_address, null) + rp_address_access_list = try(local.device_config[each.value.name].ipv6_pim.rp_address_access_list, local.defaults.iosxe.configuration.ipv6_pim.rp_address_access_list, null) + rp_address_bidir = try(local.device_config[each.value.name].ipv6_pim.rp_address_bidir, local.defaults.iosxe.configuration.ipv6_pim.rp_address_bidir, null) + + vrfs = try(length(local.device_config[each.value.name].ipv6_pim.vrfs) == 0, true) ? null : [for vrf in local.device_config[each.value.name].ipv6_pim.vrfs : { + vrf = try(vrf.vrf, local.defaults.iosxe.configuration.ipv6_pim.vrfs.vrf, null) + rp_address = try(vrf.rp_address, local.defaults.iosxe.configuration.ipv6_pim.vrfs.rp_address, null) + rp_address_access_list = try(vrf.rp_address_access_list, local.defaults.iosxe.configuration.ipv6_pim.vrfs.rp_address_access_list, null) + rp_address_bidir = try(vrf.rp_address_bidir, local.defaults.iosxe.configuration.ipv6_pim.vrfs.rp_address_bidir, null) + }] + + depends_on = [ + iosxe_vrf.vrf + ] +} + From 8dc4aed8e71a15166f3ec2a70cbfeb65620aa9e6 Mon Sep 17 00:00:00 2001 From: Blake Becton <238314145+tech-of-all-trades@users.noreply.github.com> Date: Thu, 20 Nov 2025 07:16:46 -0500 Subject: [PATCH 2/2] fix: Correct module code incorrectly concatenating ipv6 prefix and prfx length --- iosxe_interfaces.tf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/iosxe_interfaces.tf b/iosxe_interfaces.tf index 130ad69..271b026 100644 --- a/iosxe_interfaces.tf +++ b/iosxe_interfaces.tf @@ -42,7 +42,7 @@ locals { source_template = try(int.source_template, local.defaults.iosxe.devices.configuration.interfaces.ethernets.source_template, []) ipv6_enable = try(int.ipv6.enable, local.defaults.iosxe.devices.configuration.interfaces.ethernets.ipv6.enable, null) ipv6_addresses = try(length(int.ipv6.addresses) == 0, true) ? null : [for addr in int.ipv6.addresses : { - prefix = "${try(addr.prefix, local.defaults.iosxe.devices.configuration.interfaces.ethernets.ipv6.addresses.prefix, null)}/${try(addr.prefix_length, local.defaults.iosxe.devices.configuration.interfaces.ethernets.ipv6.addresses.prefix_length, null)}" + prefix = try(addr.prefix, local.defaults.iosxe.devices.configuration.interfaces.ethernets.ipv6.addresses.prefix, null) eui64 = try(addr.eui64, local.defaults.iosxe.devices.configuration.interfaces.ethernets.ipv6.addresses.eui64, null) }] ipv6_link_local_addresses = try(length(int.ipv6.link_local_addresses) == 0, true) ? null : [for addr in int.ipv6.link_local_addresses : { @@ -482,7 +482,7 @@ locals { source_template = try(int.source_template, local.defaults.iosxe.devices.configuration.interfaces.loopbacks.source_template, []) ipv6_enable = try(int.ipv6.enable, local.defaults.iosxe.devices.configuration.interfaces.loopbacks.ipv6.enable, null) ipv6_addresses = try(length(int.ipv6.addresses) == 0, true) ? null : [for addr in int.ipv6.addresses : { - prefix = "${try(addr.prefix, local.defaults.iosxe.devices.configuration.interfaces.loopbacks.ipv6.addresses.prefix, null)}/${try(addr.prefix_length, local.defaults.iosxe.devices.configuration.interfaces.loopbacks.ipv6.addresses.prefix_length, null)}" + prefix = try(addr.prefix, local.defaults.iosxe.devices.configuration.interfaces.loopbacks.ipv6.addresses.prefix, null) eui64 = try(addr.eui64, local.defaults.iosxe.devices.configuration.interfaces.loopbacks.ipv6.addresses.eui64, null) }] ipv6_link_local_addresses = try(length(int.ipv6.link_local_addresses) == 0, true) ? null : [for addr in int.ipv6.link_local_addresses : { @@ -711,7 +711,7 @@ locals { unnumbered = try("${try(int.ipv4.unnumbered_interface_type, local.defaults.iosxe.devices.configuration.interfaces.vlans.ipv4.unnumbered_interface_type)}${try(int.ipv4.unnumbered_interface_id, local.defaults.iosxe.devices.configuration.interfaces.vlans.ipv4.unnumbered_interface_id)}", null) ipv6_enable = try(int.ipv6.enable, local.defaults.iosxe.devices.configuration.interfaces.vlans.ipv6.enable, null) ipv6_addresses = try(length(int.ipv6.addresses) == 0, true) ? null : [for addr in int.ipv6.addresses : { - prefix = "${try(addr.prefix, local.defaults.iosxe.devices.configuration.interfaces.vlans.ipv6.addresses.prefix, null)}/${try(addr.prefix_length, local.defaults.iosxe.devices.configuration.interfaces.vlans.ipv6.addresses.prefix_length, null)}" + prefix = try(addr.prefix, local.defaults.iosxe.devices.configuration.interfaces.vlans.ipv6.addresses.prefix, null) eui64 = try(addr.eui64, local.defaults.iosxe.devices.configuration.interfaces.vlans.ipv6.addresses.eui64, null) }] ipv6_link_local_addresses = try(length(int.ipv6.link_local_addresses) == 0, true) ? null : [for addr in int.ipv6.link_local_addresses : { @@ -1287,7 +1287,7 @@ locals { ip_unreachables = try(sub.ipv4.unreachables, local.defaults.iosxe.devices.configuration.interfaces.port_channels.subinterfaces.ipv4.unreachables, null) ipv6_enable = try(sub.ipv6.enable, local.defaults.iosxe.devices.configuration.interfaces.port_channels.subinterfaces.ipv6.enable, null) ipv6_addresses = try(length(sub.ipv6.addresses) == 0, true) ? null : [for addr in sub.ipv6.addresses : { - prefix = "${try(addr.prefix, local.defaults.iosxe.devices.configuration.interfaces.port_channels.subinterfaces.ipv6.addresses.prefix, null)}/${try(addr.prefix_length, local.defaults.iosxe.devices.configuration.interfaces.port_channels.subinterfaces.ipv6.addresses.prefix_length, null)}" + prefix = try(addr.prefix, local.defaults.iosxe.devices.configuration.interfaces.port_channels.subinterfaces.ipv6.addresses.prefix, null) eui_64 = try(addr.eui_64, local.defaults.iosxe.devices.configuration.interfaces.port_channels.subinterfaces.ipv6.addresses.eui_64, null) }] ipv6_link_local_addresses = try(length(sub.ipv6.link_local_addresses) == 0, true) ? null : [for addr in sub.ipv6.link_local_addresses : {