From 4a16d443e2e23a5a890e2628f0df902b408d7571 Mon Sep 17 00:00:00 2001 From: Jeremy Spencer Date: Fri, 31 Oct 2025 17:11:43 -0400 Subject: [PATCH 1/2] feat: Add support for BGP maximum-paths for ebgp and ibgp --- CHANGELOG.md | 5 ++- docs/data-sources/bgp_address_family_ipv4.md | 2 + .../bgp_address_family_ipv4_vrf.md | 2 + docs/guides/changelog.md | 5 ++- docs/resources/bgp_address_family_ipv4.md | 6 +++ docs/resources/bgp_address_family_ipv4_vrf.md | 6 ++- .../iosxe_bgp_address_family_ipv4/resource.tf | 2 + .../resource.tf | 3 +- gen/definitions/bgp_address_family_ipv4.yaml | 6 +++ .../bgp_address_family_ipv4_vrf.yaml | 9 +++- ...ta_source_iosxe_bgp_address_family_ipv4.go | 8 ++++ ...urce_iosxe_bgp_address_family_ipv4_test.go | 4 ++ ...ource_iosxe_bgp_address_family_ipv4_vrf.go | 8 ++++ ..._iosxe_bgp_address_family_ipv4_vrf_test.go | 6 ++- .../model_iosxe_bgp_address_family_ipv4.go | 44 +++++++++++++++++++ ...model_iosxe_bgp_address_family_ipv4_vrf.go | 36 +++++++++++++++ .../resource_iosxe_bgp_address_family_ipv4.go | 14 ++++++ ...urce_iosxe_bgp_address_family_ipv4_test.go | 4 ++ ...ource_iosxe_bgp_address_family_ipv4_vrf.go | 14 ++++++ ..._iosxe_bgp_address_family_ipv4_vrf_test.go | 6 ++- templates/guides/changelog.md.tmpl | 5 ++- 21 files changed, 182 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4c577638..99485aed9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Add `evpn_ethernet_segments` attribute to `iosxe_interface_ethernet` and `iosxe_interface_port_channel` resources and data sources - Add `set_ip_next_hop_unchanged` attribute to `iosxe_route_map` resource and data source - Enhance `set_communities` attribute documentation in `iosxe_route_map` to clarify support for well-known BGP community values (internet, local-AS, no-advertise, no-export, gshut) +- Add support for maximum-path (ebgp and ibgp) for BGP ipv4 unicast with VRF ## 0.9.3 @@ -20,7 +21,7 @@ - Add `passive_interface_disable_*` attributes to `iosxe_ospf` and `iosxe_ospf_vrf` resources and data sources - Fix issue with destroying `iosxe_interface_ethernet` resources - Change route target attributes of `iosxe_vrf` from type "List" to "Set" -- Add `role_based_enforcement` attributes to `iosxe_cts` +- Add `role_based_enforcement` attributes to `iosxe_cts` - Add `tftp_source_interface_*` attributes to `iosxe_system` resource and data source - Add `hash` attribute to `iosxe_crypto_pki` resource and data source - Add `snooping_information_option`, `snooping_information_option_allow_untrusted` and `snooping_information_option_format_remote_id_string` attributes to `iosxe_dhcp` resource and data source @@ -65,7 +66,7 @@ - Add `level`, `list_name`, `action_type`, `broadcast`, `group_broadcast`, `group_logger`, `group1_group`, `group2_group`, `group3_group`, `group4_group`, `name`, `default`, `none`, `start_stop_broadcast`, `start_stop_logger`, `start_stop_group1`, `start_stop_group2`, `start_stop_group3`, `start_stop_group4`, `stop_only_broadcast`, `stop_only_logger`, `stop_only_group1`, `stop_only_group2`, `stop_only_group3`, `stop_only_group4`, `wait_start_broadcast`, `wait_start_logger`, `wait_start_group1`, `wait_start_group2`, `wait_start_group3`, `wait_start_group4`, `name`, `none`, `start_stop_broadcast`, `start_stop_logger`, `start_stop_group1`, `start_stop_group2`, `start_stop_group3`, `start_stop_group4`, `stop_only_broadcast`, `stop_only_logger`, `stop_only_group1`, `stop_only_group2`, `stop_only_group3`, `stop_only_group4`, `wait_start_broadcast`, `wait_start_logger`, `wait_start_group1`, `wait_start_group2`, `wait_start_group3`, and `wait_start_group4` attributes to `iosxe_aaa_accounting` resource and data source - Add `enable_default_group1_cache`, `enable_default_group1_enable`, `enable_default_group1_group`, `enable_default_group1_line`, `enable_default_group1_none`, `enable_default_group2_cache`, `enable_default_group2_enable`, `enable_default_group2_group`, `enable_default_group2_line`, `enable_default_group2_none`, `enable_default_group3_cache`, `enable_default_group3_enable`, `enable_default_group3_group`, `enable_default_group3_line`, `enable_default_group3_none`, `enable_default_group4_cache`, `enable_default_group4_enable`, `enable_default_group4_group`, `enable_default_group4_line`, and `enable_default_group4_none` attributes to `iosxe_aaa_authentication` resource and data source - Add `level`, `list_name`, `a1_group`, `a1_local`, `a1_if_authenticated`, `a1_none`, `a1_radius`, `a1_tacacs`, `a2_group`, `a2_local`, `a2_if_authenticated`, `a2_none`, `a2_radius`, `a2_tacacs`, `a3_group`, `a3_local`, `a3_if_authenticated`, `a3_none`, `a3_radius`, `a3_tacacs`, `a4_group`, `a4_local`, `a4_if_authenticated`, `a4_none`, `a4_radius`, `a4_tacacs`, `name`, `group1_cache`, `group1_group`, `group1_radius`, and `group1_tacacs` attributes to `iosxe_aaa_authorization` resource and data source -- Add `vrf`, `local_authentication_type`, `local_authorization`, and `local_auth_max_fail_attempts` attributes to `iosxe_aaa` resrouce and data source +- Add `vrf`, `local_authentication_type`, `local_authorization`, and `local_auth_max_fail_attempts` attributes to `iosxe_aaa` resrouce and data source - Add `icmp_named_msg_type`, `destination_port_equal_2`, `destination_port_equal_3`, `destination_port_equal_4`, `destination_port_equal_5`, `destination_port_equal_6`, `destination_port_equal_7`, `destination_port_equal_8`, `destination_port_equal_9`, `destination_port_equal_10`, `icmp_msg_type`, and `icmp_msg_code` attributes to `iosxe_access_list_extended` resource and data source - Add `iosxe_access_list_role_based` resource and data source - Add `filter_lists_cdp` attribute to `iosxe_device_sensor` resource and data source diff --git a/docs/data-sources/bgp_address_family_ipv4.md b/docs/data-sources/bgp_address_family_ipv4.md index ba7b4ac1d..f2565fcaf 100644 --- a/docs/data-sources/bgp_address_family_ipv4.md +++ b/docs/data-sources/bgp_address_family_ipv4.md @@ -39,6 +39,8 @@ data "iosxe_bgp_address_family_ipv4" "example" { - `ipv4_unicast_distance_bgp_external` (Number) - `ipv4_unicast_distance_bgp_internal` (Number) - `ipv4_unicast_distance_bgp_local` (Number) +- `ipv4_unicast_maximum_paths_ebgp` (Number) eBGP-multipath +- `ipv4_unicast_maximum_paths_ibgp` (Number) iBGP-multipath - `ipv4_unicast_networks` (Attributes List) Specify a network to announce via BGP (see [below for nested schema](#nestedatt--ipv4_unicast_networks)) - `ipv4_unicast_networks_mask` (Attributes List) Specify a network to announce via BGP (see [below for nested schema](#nestedatt--ipv4_unicast_networks_mask)) - `ipv4_unicast_redistribute_connected` (Boolean) Connected diff --git a/docs/data-sources/bgp_address_family_ipv4_vrf.md b/docs/data-sources/bgp_address_family_ipv4_vrf.md index d0664c20a..165f04a6e 100644 --- a/docs/data-sources/bgp_address_family_ipv4_vrf.md +++ b/docs/data-sources/bgp_address_family_ipv4_vrf.md @@ -47,6 +47,8 @@ Read-Only: - `ipv4_unicast_distance_bgp_external` (Number) - `ipv4_unicast_distance_bgp_internal` (Number) - `ipv4_unicast_distance_bgp_local` (Number) +- `ipv4_unicast_maximum_paths_ebgp` (Number) eBGP-multipath +- `ipv4_unicast_maximum_paths_ibgp` (Number) - `ipv4_unicast_networks` (Attributes List) Specify a network to announce via BGP (see [below for nested schema](#nestedatt--vrfs--ipv4_unicast_networks)) - `ipv4_unicast_networks_mask` (Attributes List) Specify a network to announce via BGP (see [below for nested schema](#nestedatt--vrfs--ipv4_unicast_networks_mask)) - `ipv4_unicast_redistribute_connected` (Boolean) Connected diff --git a/docs/guides/changelog.md b/docs/guides/changelog.md index 3db265d5a..d0d7624c4 100644 --- a/docs/guides/changelog.md +++ b/docs/guides/changelog.md @@ -15,6 +15,7 @@ description: |- - Add `evpn_ethernet_segments` attribute to `iosxe_interface_ethernet` and `iosxe_interface_port_channel` resources and data sources - Add `set_ip_next_hop_unchanged` attribute to `iosxe_route_map` resource and data source - Enhance `set_communities` attribute documentation in `iosxe_route_map` to clarify support for well-known BGP community values (internet, local-AS, no-advertise, no-export, gshut) +- Add support for maximum-path (ebgp and ibgp) for BGP ipv4 unicast with VRF ## 0.9.3 @@ -29,7 +30,7 @@ description: |- - Add `passive_interface_disable_*` attributes to `iosxe_ospf` and `iosxe_ospf_vrf` resources and data sources - Fix issue with destroying `iosxe_interface_ethernet` resources - Change route target attributes of `iosxe_vrf` from type "List" to "Set" -- Add `role_based_enforcement` attributes to `iosxe_cts` +- Add `role_based_enforcement` attributes to `iosxe_cts` - Add `tftp_source_interface_*` attributes to `iosxe_system` resource and data source - Add `hash` attribute to `iosxe_crypto_pki` resource and data source - Add `snooping_information_option`, `snooping_information_option_allow_untrusted` and `snooping_information_option_format_remote_id_string` attributes to `iosxe_dhcp` resource and data source @@ -74,7 +75,7 @@ description: |- - Add `level`, `list_name`, `action_type`, `broadcast`, `group_broadcast`, `group_logger`, `group1_group`, `group2_group`, `group3_group`, `group4_group`, `name`, `default`, `none`, `start_stop_broadcast`, `start_stop_logger`, `start_stop_group1`, `start_stop_group2`, `start_stop_group3`, `start_stop_group4`, `stop_only_broadcast`, `stop_only_logger`, `stop_only_group1`, `stop_only_group2`, `stop_only_group3`, `stop_only_group4`, `wait_start_broadcast`, `wait_start_logger`, `wait_start_group1`, `wait_start_group2`, `wait_start_group3`, `wait_start_group4`, `name`, `none`, `start_stop_broadcast`, `start_stop_logger`, `start_stop_group1`, `start_stop_group2`, `start_stop_group3`, `start_stop_group4`, `stop_only_broadcast`, `stop_only_logger`, `stop_only_group1`, `stop_only_group2`, `stop_only_group3`, `stop_only_group4`, `wait_start_broadcast`, `wait_start_logger`, `wait_start_group1`, `wait_start_group2`, `wait_start_group3`, and `wait_start_group4` attributes to `iosxe_aaa_accounting` resource and data source - Add `enable_default_group1_cache`, `enable_default_group1_enable`, `enable_default_group1_group`, `enable_default_group1_line`, `enable_default_group1_none`, `enable_default_group2_cache`, `enable_default_group2_enable`, `enable_default_group2_group`, `enable_default_group2_line`, `enable_default_group2_none`, `enable_default_group3_cache`, `enable_default_group3_enable`, `enable_default_group3_group`, `enable_default_group3_line`, `enable_default_group3_none`, `enable_default_group4_cache`, `enable_default_group4_enable`, `enable_default_group4_group`, `enable_default_group4_line`, and `enable_default_group4_none` attributes to `iosxe_aaa_authentication` resource and data source - Add `level`, `list_name`, `a1_group`, `a1_local`, `a1_if_authenticated`, `a1_none`, `a1_radius`, `a1_tacacs`, `a2_group`, `a2_local`, `a2_if_authenticated`, `a2_none`, `a2_radius`, `a2_tacacs`, `a3_group`, `a3_local`, `a3_if_authenticated`, `a3_none`, `a3_radius`, `a3_tacacs`, `a4_group`, `a4_local`, `a4_if_authenticated`, `a4_none`, `a4_radius`, `a4_tacacs`, `name`, `group1_cache`, `group1_group`, `group1_radius`, and `group1_tacacs` attributes to `iosxe_aaa_authorization` resource and data source -- Add `vrf`, `local_authentication_type`, `local_authorization`, and `local_auth_max_fail_attempts` attributes to `iosxe_aaa` resrouce and data source +- Add `vrf`, `local_authentication_type`, `local_authorization`, and `local_auth_max_fail_attempts` attributes to `iosxe_aaa` resrouce and data source - Add `icmp_named_msg_type`, `destination_port_equal_2`, `destination_port_equal_3`, `destination_port_equal_4`, `destination_port_equal_5`, `destination_port_equal_6`, `destination_port_equal_7`, `destination_port_equal_8`, `destination_port_equal_9`, `destination_port_equal_10`, `icmp_msg_type`, and `icmp_msg_code` attributes to `iosxe_access_list_extended` resource and data source - Add `iosxe_access_list_role_based` resource and data source - Add `filter_lists_cdp` attribute to `iosxe_device_sensor` resource and data source diff --git a/docs/resources/bgp_address_family_ipv4.md b/docs/resources/bgp_address_family_ipv4.md index c5c55d5de..a40d67719 100644 --- a/docs/resources/bgp_address_family_ipv4.md +++ b/docs/resources/bgp_address_family_ipv4.md @@ -49,6 +49,8 @@ resource "iosxe_bgp_address_family_ipv4" "example" { ipv4_unicast_distance_bgp_external = 20 ipv4_unicast_distance_bgp_internal = 200 ipv4_unicast_distance_bgp_local = 200 + ipv4_unicast_maximum_paths_ebgp = 2 + ipv4_unicast_maximum_paths_ibgp = 2 } ``` @@ -70,6 +72,10 @@ resource "iosxe_bgp_address_family_ipv4" "example" { - `ipv4_unicast_distance_bgp_external` (Number) - Range: `1`-`255` - `ipv4_unicast_distance_bgp_internal` (Number) - Range: `1`-`255` - `ipv4_unicast_distance_bgp_local` (Number) - Range: `1`-`255` +- `ipv4_unicast_maximum_paths_ebgp` (Number) eBGP-multipath + - Range: `1`-`32` +- `ipv4_unicast_maximum_paths_ibgp` (Number) iBGP-multipath + - Range: `1`-`32` - `ipv4_unicast_networks` (Attributes List) Specify a network to announce via BGP (see [below for nested schema](#nestedatt--ipv4_unicast_networks)) - `ipv4_unicast_networks_mask` (Attributes List) Specify a network to announce via BGP (see [below for nested schema](#nestedatt--ipv4_unicast_networks_mask)) - `ipv4_unicast_redistribute_connected` (Boolean) Connected diff --git a/docs/resources/bgp_address_family_ipv4_vrf.md b/docs/resources/bgp_address_family_ipv4_vrf.md index a26bc94c1..87779f453 100644 --- a/docs/resources/bgp_address_family_ipv4_vrf.md +++ b/docs/resources/bgp_address_family_ipv4_vrf.md @@ -22,7 +22,6 @@ resource "iosxe_bgp_address_family_ipv4_vrf" "example" { ipv4_unicast_advertise_l2vpn_evpn = true ipv4_unicast_redistribute_connected = true ipv4_unicast_router_id_loopback = 101 - ipv4_unicast_router_id_ip = "10.1.1.1" ipv4_unicast_aggregate_addresses = [ { ipv4_address = "50.0.0.0" @@ -55,6 +54,8 @@ resource "iosxe_bgp_address_family_ipv4_vrf" "example" { ipv4_unicast_distance_bgp_external = 20 ipv4_unicast_distance_bgp_internal = 200 ipv4_unicast_distance_bgp_local = 200 + ipv4_unicast_maximum_paths_ebgp = 2 + ipv4_unicast_maximum_paths_ibgp = 2 } ] } @@ -94,6 +95,9 @@ Optional: - `ipv4_unicast_distance_bgp_external` (Number) - Range: `1`-`255` - `ipv4_unicast_distance_bgp_internal` (Number) - Range: `1`-`255` - `ipv4_unicast_distance_bgp_local` (Number) - Range: `1`-`255` +- `ipv4_unicast_maximum_paths_ebgp` (Number) eBGP-multipath + - Range: `1`-`32` +- `ipv4_unicast_maximum_paths_ibgp` (Number) - Range: `1`-`32` - `ipv4_unicast_networks` (Attributes List) Specify a network to announce via BGP (see [below for nested schema](#nestedatt--vrfs--ipv4_unicast_networks)) - `ipv4_unicast_networks_mask` (Attributes List) Specify a network to announce via BGP (see [below for nested schema](#nestedatt--vrfs--ipv4_unicast_networks_mask)) - `ipv4_unicast_redistribute_connected` (Boolean) Connected diff --git a/examples/resources/iosxe_bgp_address_family_ipv4/resource.tf b/examples/resources/iosxe_bgp_address_family_ipv4/resource.tf index f6f64f7fd..5df6999dc 100644 --- a/examples/resources/iosxe_bgp_address_family_ipv4/resource.tf +++ b/examples/resources/iosxe_bgp_address_family_ipv4/resource.tf @@ -34,4 +34,6 @@ resource "iosxe_bgp_address_family_ipv4" "example" { ipv4_unicast_distance_bgp_external = 20 ipv4_unicast_distance_bgp_internal = 200 ipv4_unicast_distance_bgp_local = 200 + ipv4_unicast_maximum_paths_ebgp = 2 + ipv4_unicast_maximum_paths_ibgp = 2 } diff --git a/examples/resources/iosxe_bgp_address_family_ipv4_vrf/resource.tf b/examples/resources/iosxe_bgp_address_family_ipv4_vrf/resource.tf index 578fc9922..319560f2f 100644 --- a/examples/resources/iosxe_bgp_address_family_ipv4_vrf/resource.tf +++ b/examples/resources/iosxe_bgp_address_family_ipv4_vrf/resource.tf @@ -7,7 +7,6 @@ resource "iosxe_bgp_address_family_ipv4_vrf" "example" { ipv4_unicast_advertise_l2vpn_evpn = true ipv4_unicast_redistribute_connected = true ipv4_unicast_router_id_loopback = 101 - ipv4_unicast_router_id_ip = "10.1.1.1" ipv4_unicast_aggregate_addresses = [ { ipv4_address = "50.0.0.0" @@ -40,6 +39,8 @@ resource "iosxe_bgp_address_family_ipv4_vrf" "example" { ipv4_unicast_distance_bgp_external = 20 ipv4_unicast_distance_bgp_internal = 200 ipv4_unicast_distance_bgp_local = 200 + ipv4_unicast_maximum_paths_ebgp = 2 + ipv4_unicast_maximum_paths_ibgp = 2 } ] } diff --git a/gen/definitions/bgp_address_family_ipv4.yaml b/gen/definitions/bgp_address_family_ipv4.yaml index 051f6c230..b5431b57c 100644 --- a/gen/definitions/bgp_address_family_ipv4.yaml +++ b/gen/definitions/bgp_address_family_ipv4.yaml @@ -77,6 +77,12 @@ attributes: example: 200 - yang_name: ipv4-unicast/distance/bgp/local example: 200 + - yang_name: ipv4-unicast/maximum-paths/ebgp + tf_name: ipv4_unicast_maximum_paths_ebgp + example: 2 + - yang_name: ipv4-unicast/maximum-paths/ibgp-leaf + tf_name: ipv4_unicast_maximum_paths_ibgp + example: 2 test_prerequisites: - path: Cisco-IOS-XE-native:native/router/Cisco-IOS-XE-bgp:bgp=65000 diff --git a/gen/definitions/bgp_address_family_ipv4_vrf.yaml b/gen/definitions/bgp_address_family_ipv4_vrf.yaml index 7ee0dd6e2..d7a8faa54 100644 --- a/gen/definitions/bgp_address_family_ipv4_vrf.yaml +++ b/gen/definitions/bgp_address_family_ipv4_vrf.yaml @@ -29,6 +29,7 @@ attributes: - yang_name: ipv4-unicast/bgp/router-id/id-choice/ip-id/ip-id xpath: ipv4-unicast/bgp/router-id/ip-id tf_name: ipv4_unicast_router_id_ip + exclude_test: true example: 10.1.1.1 - yang_name: ipv4-unicast/aggregate-address tf_name: ipv4_unicast_aggregate_addresses @@ -110,7 +111,13 @@ attributes: example: 200 - yang_name: ipv4-unicast/distance/bgp/local example: 200 - + - yang_name: ipv4-unicast/maximum-paths/ebgp + tf_name: ipv4_unicast_maximum_paths_ebgp + example: 2 + - yang_name: ipv4-unicast/maximum-paths/ibgp/ibgp-choice/max/max + tf_name: ipv4_unicast_maximum_paths_ibgp + xpath: ipv4-unicast/maximum-paths/ibgp/max + example: 2 test_prerequisites: - path: Cisco-IOS-XE-native:native/vrf/definition=VRF1 no_delete: true diff --git a/internal/provider/data_source_iosxe_bgp_address_family_ipv4.go b/internal/provider/data_source_iosxe_bgp_address_family_ipv4.go index 275fc961d..e148fc09e 100644 --- a/internal/provider/data_source_iosxe_bgp_address_family_ipv4.go +++ b/internal/provider/data_source_iosxe_bgp_address_family_ipv4.go @@ -179,6 +179,14 @@ func (d *BGPAddressFamilyIPv4DataSource) Schema(ctx context.Context, req datasou MarkdownDescription: "", Computed: true, }, + "ipv4_unicast_maximum_paths_ebgp": schema.Int64Attribute{ + MarkdownDescription: "eBGP-multipath", + Computed: true, + }, + "ipv4_unicast_maximum_paths_ibgp": schema.Int64Attribute{ + MarkdownDescription: "iBGP-multipath", + Computed: true, + }, }, } } diff --git a/internal/provider/data_source_iosxe_bgp_address_family_ipv4_test.go b/internal/provider/data_source_iosxe_bgp_address_family_ipv4_test.go index 9cd23f028..fba33fed5 100644 --- a/internal/provider/data_source_iosxe_bgp_address_family_ipv4_test.go +++ b/internal/provider/data_source_iosxe_bgp_address_family_ipv4_test.go @@ -49,6 +49,8 @@ func TestAccDataSourceIosxeBGPAddressFamilyIPv4(t *testing.T) { checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_address_family_ipv4.test", "ipv4_unicast_distance_bgp_external", "20")) checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_address_family_ipv4.test", "ipv4_unicast_distance_bgp_internal", "200")) checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_address_family_ipv4.test", "ipv4_unicast_distance_bgp_local", "200")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_address_family_ipv4.test", "ipv4_unicast_maximum_paths_ebgp", "2")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_address_family_ipv4.test", "ipv4_unicast_maximum_paths_ibgp", "2")) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, @@ -108,6 +110,8 @@ func testAccDataSourceIosxeBGPAddressFamilyIPv4Config() string { config += ` ipv4_unicast_distance_bgp_external = 20` + "\n" config += ` ipv4_unicast_distance_bgp_internal = 200` + "\n" config += ` ipv4_unicast_distance_bgp_local = 200` + "\n" + config += ` ipv4_unicast_maximum_paths_ebgp = 2` + "\n" + config += ` ipv4_unicast_maximum_paths_ibgp = 2` + "\n" config += ` depends_on = [iosxe_restconf.PreReq0, ]` + "\n" config += `}` + "\n" diff --git a/internal/provider/data_source_iosxe_bgp_address_family_ipv4_vrf.go b/internal/provider/data_source_iosxe_bgp_address_family_ipv4_vrf.go index b2e474882..e15103104 100644 --- a/internal/provider/data_source_iosxe_bgp_address_family_ipv4_vrf.go +++ b/internal/provider/data_source_iosxe_bgp_address_family_ipv4_vrf.go @@ -208,6 +208,14 @@ func (d *BGPAddressFamilyIPv4VRFDataSource) Schema(ctx context.Context, req data MarkdownDescription: "", Computed: true, }, + "ipv4_unicast_maximum_paths_ebgp": schema.Int64Attribute{ + MarkdownDescription: "eBGP-multipath", + Computed: true, + }, + "ipv4_unicast_maximum_paths_ibgp": schema.Int64Attribute{ + MarkdownDescription: "", + Computed: true, + }, }, }, }, diff --git a/internal/provider/data_source_iosxe_bgp_address_family_ipv4_vrf_test.go b/internal/provider/data_source_iosxe_bgp_address_family_ipv4_vrf_test.go index 2fbaf9fec..3371b428f 100644 --- a/internal/provider/data_source_iosxe_bgp_address_family_ipv4_vrf_test.go +++ b/internal/provider/data_source_iosxe_bgp_address_family_ipv4_vrf_test.go @@ -36,7 +36,6 @@ func TestAccDataSourceIosxeBGPAddressFamilyIPv4VRF(t *testing.T) { checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_advertise_l2vpn_evpn", "true")) checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_redistribute_connected", "true")) checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_router_id_loopback", "101")) - checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_router_id_ip", "10.1.1.1")) checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_aggregate_addresses.0.ipv4_address", "50.0.0.0")) checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_aggregate_addresses.0.ipv4_mask", "255.255.0.0")) checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_redistribute_static", "true")) @@ -53,6 +52,8 @@ func TestAccDataSourceIosxeBGPAddressFamilyIPv4VRF(t *testing.T) { checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_distance_bgp_external", "20")) checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_distance_bgp_internal", "200")) checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_distance_bgp_local", "200")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_maximum_paths_ebgp", "2")) + checks = append(checks, resource.TestCheckResourceAttr("data.iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_maximum_paths_ibgp", "2")) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, @@ -114,7 +115,6 @@ func testAccDataSourceIosxeBGPAddressFamilyIPv4VRFConfig() string { config += ` ipv4_unicast_advertise_l2vpn_evpn = true` + "\n" config += ` ipv4_unicast_redistribute_connected = true` + "\n" config += ` ipv4_unicast_router_id_loopback = 101` + "\n" - config += ` ipv4_unicast_router_id_ip = "10.1.1.1"` + "\n" config += ` ipv4_unicast_aggregate_addresses = [{` + "\n" config += ` ipv4_address = "50.0.0.0"` + "\n" config += ` ipv4_mask = "255.255.0.0"` + "\n" @@ -139,6 +139,8 @@ func testAccDataSourceIosxeBGPAddressFamilyIPv4VRFConfig() string { config += ` ipv4_unicast_distance_bgp_external = 20` + "\n" config += ` ipv4_unicast_distance_bgp_internal = 200` + "\n" config += ` ipv4_unicast_distance_bgp_local = 200` + "\n" + config += ` ipv4_unicast_maximum_paths_ebgp = 2` + "\n" + config += ` ipv4_unicast_maximum_paths_ibgp = 2` + "\n" config += ` }]` + "\n" config += ` depends_on = [iosxe_restconf.PreReq0, iosxe_restconf.PreReq1, iosxe_restconf.PreReq2, ]` + "\n" config += `}` + "\n" diff --git a/internal/provider/model_iosxe_bgp_address_family_ipv4.go b/internal/provider/model_iosxe_bgp_address_family_ipv4.go index 2696107f2..1d95d63b9 100644 --- a/internal/provider/model_iosxe_bgp_address_family_ipv4.go +++ b/internal/provider/model_iosxe_bgp_address_family_ipv4.go @@ -53,6 +53,8 @@ type BGPAddressFamilyIPv4 struct { Ipv4UnicastDistanceBgpExternal types.Int64 `tfsdk:"ipv4_unicast_distance_bgp_external"` Ipv4UnicastDistanceBgpInternal types.Int64 `tfsdk:"ipv4_unicast_distance_bgp_internal"` Ipv4UnicastDistanceBgpLocal types.Int64 `tfsdk:"ipv4_unicast_distance_bgp_local"` + Ipv4UnicastMaximumPathsEbgp types.Int64 `tfsdk:"ipv4_unicast_maximum_paths_ebgp"` + Ipv4UnicastMaximumPathsIbgp types.Int64 `tfsdk:"ipv4_unicast_maximum_paths_ibgp"` } type BGPAddressFamilyIPv4Data struct { @@ -69,6 +71,8 @@ type BGPAddressFamilyIPv4Data struct { Ipv4UnicastDistanceBgpExternal types.Int64 `tfsdk:"ipv4_unicast_distance_bgp_external"` Ipv4UnicastDistanceBgpInternal types.Int64 `tfsdk:"ipv4_unicast_distance_bgp_internal"` Ipv4UnicastDistanceBgpLocal types.Int64 `tfsdk:"ipv4_unicast_distance_bgp_local"` + Ipv4UnicastMaximumPathsEbgp types.Int64 `tfsdk:"ipv4_unicast_maximum_paths_ebgp"` + Ipv4UnicastMaximumPathsIbgp types.Int64 `tfsdk:"ipv4_unicast_maximum_paths_ibgp"` } type BGPAddressFamilyIPv4Ipv4UnicastAggregateAddresses struct { Ipv4Address types.String `tfsdk:"ipv4_address"` @@ -143,6 +147,12 @@ func (data BGPAddressFamilyIPv4) toBody(ctx context.Context) string { if !data.Ipv4UnicastDistanceBgpLocal.IsNull() && !data.Ipv4UnicastDistanceBgpLocal.IsUnknown() { body, _ = sjson.Set(body, helpers.LastElement(data.getPath())+"."+"ipv4-unicast.distance.bgp.local", strconv.FormatInt(data.Ipv4UnicastDistanceBgpLocal.ValueInt64(), 10)) } + if !data.Ipv4UnicastMaximumPathsEbgp.IsNull() && !data.Ipv4UnicastMaximumPathsEbgp.IsUnknown() { + body, _ = sjson.Set(body, helpers.LastElement(data.getPath())+"."+"ipv4-unicast.maximum-paths.ebgp", strconv.FormatInt(data.Ipv4UnicastMaximumPathsEbgp.ValueInt64(), 10)) + } + if !data.Ipv4UnicastMaximumPathsIbgp.IsNull() && !data.Ipv4UnicastMaximumPathsIbgp.IsUnknown() { + body, _ = sjson.Set(body, helpers.LastElement(data.getPath())+"."+"ipv4-unicast.maximum-paths.ibgp-leaf", strconv.FormatInt(data.Ipv4UnicastMaximumPathsIbgp.ValueInt64(), 10)) + } if len(data.Ipv4UnicastAggregateAddresses) > 0 { body, _ = sjson.Set(body, helpers.LastElement(data.getPath())+"."+"ipv4-unicast.aggregate-address", []interface{}{}) for index, item := range data.Ipv4UnicastAggregateAddresses { @@ -425,6 +435,16 @@ func (data *BGPAddressFamilyIPv4) updateFromBody(ctx context.Context, res gjson. } else { data.Ipv4UnicastDistanceBgpLocal = types.Int64Null() } + if value := res.Get(prefix + "ipv4-unicast.maximum-paths.ebgp"); value.Exists() && !data.Ipv4UnicastMaximumPathsEbgp.IsNull() { + data.Ipv4UnicastMaximumPathsEbgp = types.Int64Value(value.Int()) + } else { + data.Ipv4UnicastMaximumPathsEbgp = types.Int64Null() + } + if value := res.Get(prefix + "ipv4-unicast.maximum-paths.ibgp-leaf"); value.Exists() && !data.Ipv4UnicastMaximumPathsIbgp.IsNull() { + data.Ipv4UnicastMaximumPathsIbgp = types.Int64Value(value.Int()) + } else { + data.Ipv4UnicastMaximumPathsIbgp = types.Int64Null() + } } // End of section. //template:end updateFromBody @@ -530,6 +550,12 @@ func (data *BGPAddressFamilyIPv4) fromBody(ctx context.Context, res gjson.Result if value := res.Get(prefix + "ipv4-unicast.distance.bgp.local"); value.Exists() { data.Ipv4UnicastDistanceBgpLocal = types.Int64Value(value.Int()) } + if value := res.Get(prefix + "ipv4-unicast.maximum-paths.ebgp"); value.Exists() { + data.Ipv4UnicastMaximumPathsEbgp = types.Int64Value(value.Int()) + } + if value := res.Get(prefix + "ipv4-unicast.maximum-paths.ibgp-leaf"); value.Exists() { + data.Ipv4UnicastMaximumPathsIbgp = types.Int64Value(value.Int()) + } } // End of section. //template:end fromBody @@ -635,6 +661,12 @@ func (data *BGPAddressFamilyIPv4Data) fromBody(ctx context.Context, res gjson.Re if value := res.Get(prefix + "ipv4-unicast.distance.bgp.local"); value.Exists() { data.Ipv4UnicastDistanceBgpLocal = types.Int64Value(value.Int()) } + if value := res.Get(prefix + "ipv4-unicast.maximum-paths.ebgp"); value.Exists() { + data.Ipv4UnicastMaximumPathsEbgp = types.Int64Value(value.Int()) + } + if value := res.Get(prefix + "ipv4-unicast.maximum-paths.ibgp-leaf"); value.Exists() { + data.Ipv4UnicastMaximumPathsIbgp = types.Int64Value(value.Int()) + } } // End of section. //template:end fromBodyData @@ -643,6 +675,12 @@ func (data *BGPAddressFamilyIPv4Data) fromBody(ctx context.Context, res gjson.Re func (data *BGPAddressFamilyIPv4) getDeletedItems(ctx context.Context, state BGPAddressFamilyIPv4) []string { deletedItems := make([]string, 0) + if !state.Ipv4UnicastMaximumPathsIbgp.IsNull() && data.Ipv4UnicastMaximumPathsIbgp.IsNull() { + deletedItems = append(deletedItems, fmt.Sprintf("%v/ipv4-unicast/maximum-paths/ibgp-leaf", state.getPath())) + } + if !state.Ipv4UnicastMaximumPathsEbgp.IsNull() && data.Ipv4UnicastMaximumPathsEbgp.IsNull() { + deletedItems = append(deletedItems, fmt.Sprintf("%v/ipv4-unicast/maximum-paths/ebgp", state.getPath())) + } if !state.Ipv4UnicastDistanceBgpLocal.IsNull() && data.Ipv4UnicastDistanceBgpLocal.IsNull() { deletedItems = append(deletedItems, fmt.Sprintf("%v/ipv4-unicast/distance/bgp/local", state.getPath())) } @@ -838,6 +876,12 @@ func (data *BGPAddressFamilyIPv4) getEmptyLeafsDelete(ctx context.Context) []str func (data *BGPAddressFamilyIPv4) getDeletePaths(ctx context.Context) []string { var deletePaths []string + if !data.Ipv4UnicastMaximumPathsIbgp.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/ipv4-unicast/maximum-paths/ibgp-leaf", data.getPath())) + } + if !data.Ipv4UnicastMaximumPathsEbgp.IsNull() { + deletePaths = append(deletePaths, fmt.Sprintf("%v/ipv4-unicast/maximum-paths/ebgp", data.getPath())) + } if !data.Ipv4UnicastDistanceBgpLocal.IsNull() { deletePaths = append(deletePaths, fmt.Sprintf("%v/ipv4-unicast/distance/bgp/local", data.getPath())) } diff --git a/internal/provider/model_iosxe_bgp_address_family_ipv4_vrf.go b/internal/provider/model_iosxe_bgp_address_family_ipv4_vrf.go index c90b55153..71f6ac539 100644 --- a/internal/provider/model_iosxe_bgp_address_family_ipv4_vrf.go +++ b/internal/provider/model_iosxe_bgp_address_family_ipv4_vrf.go @@ -68,6 +68,8 @@ type BGPAddressFamilyIPv4VRFVrfs struct { Ipv4UnicastDistanceBgpExternal types.Int64 `tfsdk:"ipv4_unicast_distance_bgp_external"` Ipv4UnicastDistanceBgpInternal types.Int64 `tfsdk:"ipv4_unicast_distance_bgp_internal"` Ipv4UnicastDistanceBgpLocal types.Int64 `tfsdk:"ipv4_unicast_distance_bgp_local"` + Ipv4UnicastMaximumPathsEbgp types.Int64 `tfsdk:"ipv4_unicast_maximum_paths_ebgp"` + Ipv4UnicastMaximumPathsIbgp types.Int64 `tfsdk:"ipv4_unicast_maximum_paths_ibgp"` } type BGPAddressFamilyIPv4VRFVrfsIpv4UnicastAggregateAddresses struct { Ipv4Address types.String `tfsdk:"ipv4_address"` @@ -161,6 +163,12 @@ func (data BGPAddressFamilyIPv4VRF) toBody(ctx context.Context) string { if !item.Ipv4UnicastDistanceBgpLocal.IsNull() && !item.Ipv4UnicastDistanceBgpLocal.IsUnknown() { body, _ = sjson.Set(body, helpers.LastElement(data.getPath())+"."+"vrf"+"."+strconv.Itoa(index)+"."+"ipv4-unicast.distance.bgp.local", strconv.FormatInt(item.Ipv4UnicastDistanceBgpLocal.ValueInt64(), 10)) } + if !item.Ipv4UnicastMaximumPathsEbgp.IsNull() && !item.Ipv4UnicastMaximumPathsEbgp.IsUnknown() { + body, _ = sjson.Set(body, helpers.LastElement(data.getPath())+"."+"vrf"+"."+strconv.Itoa(index)+"."+"ipv4-unicast.maximum-paths.ebgp", strconv.FormatInt(item.Ipv4UnicastMaximumPathsEbgp.ValueInt64(), 10)) + } + if !item.Ipv4UnicastMaximumPathsIbgp.IsNull() && !item.Ipv4UnicastMaximumPathsIbgp.IsUnknown() { + body, _ = sjson.Set(body, helpers.LastElement(data.getPath())+"."+"vrf"+"."+strconv.Itoa(index)+"."+"ipv4-unicast.maximum-paths.ibgp.max", strconv.FormatInt(item.Ipv4UnicastMaximumPathsIbgp.ValueInt64(), 10)) + } if len(item.Ipv4UnicastAggregateAddresses) > 0 { body, _ = sjson.Set(body, helpers.LastElement(data.getPath())+"."+"vrf"+"."+strconv.Itoa(index)+"."+"ipv4-unicast.aggregate-address", []interface{}{}) for cindex, citem := range item.Ipv4UnicastAggregateAddresses { @@ -520,6 +528,16 @@ func (data *BGPAddressFamilyIPv4VRF) updateFromBody(ctx context.Context, res gjs } else { data.Vrfs[i].Ipv4UnicastDistanceBgpLocal = types.Int64Null() } + if value := r.Get("ipv4-unicast.maximum-paths.ebgp"); value.Exists() && !data.Vrfs[i].Ipv4UnicastMaximumPathsEbgp.IsNull() { + data.Vrfs[i].Ipv4UnicastMaximumPathsEbgp = types.Int64Value(value.Int()) + } else { + data.Vrfs[i].Ipv4UnicastMaximumPathsEbgp = types.Int64Null() + } + if value := r.Get("ipv4-unicast.maximum-paths.ibgp.max"); value.Exists() && !data.Vrfs[i].Ipv4UnicastMaximumPathsIbgp.IsNull() { + data.Vrfs[i].Ipv4UnicastMaximumPathsIbgp = types.Int64Value(value.Int()) + } else { + data.Vrfs[i].Ipv4UnicastMaximumPathsIbgp = types.Int64Null() + } } } @@ -654,6 +672,12 @@ func (data *BGPAddressFamilyIPv4VRF) fromBody(ctx context.Context, res gjson.Res if cValue := v.Get("ipv4-unicast.distance.bgp.local"); cValue.Exists() { item.Ipv4UnicastDistanceBgpLocal = types.Int64Value(cValue.Int()) } + if cValue := v.Get("ipv4-unicast.maximum-paths.ebgp"); cValue.Exists() { + item.Ipv4UnicastMaximumPathsEbgp = types.Int64Value(cValue.Int()) + } + if cValue := v.Get("ipv4-unicast.maximum-paths.ibgp.max"); cValue.Exists() { + item.Ipv4UnicastMaximumPathsIbgp = types.Int64Value(cValue.Int()) + } data.Vrfs = append(data.Vrfs, item) return true }) @@ -791,6 +815,12 @@ func (data *BGPAddressFamilyIPv4VRFData) fromBody(ctx context.Context, res gjson if cValue := v.Get("ipv4-unicast.distance.bgp.local"); cValue.Exists() { item.Ipv4UnicastDistanceBgpLocal = types.Int64Value(cValue.Int()) } + if cValue := v.Get("ipv4-unicast.maximum-paths.ebgp"); cValue.Exists() { + item.Ipv4UnicastMaximumPathsEbgp = types.Int64Value(cValue.Int()) + } + if cValue := v.Get("ipv4-unicast.maximum-paths.ibgp.max"); cValue.Exists() { + item.Ipv4UnicastMaximumPathsIbgp = types.Int64Value(cValue.Int()) + } data.Vrfs = append(data.Vrfs, item) return true }) @@ -821,6 +851,12 @@ func (data *BGPAddressFamilyIPv4VRF) getDeletedItems(ctx context.Context, state found = false } if found { + if !state.Vrfs[i].Ipv4UnicastMaximumPathsIbgp.IsNull() && data.Vrfs[j].Ipv4UnicastMaximumPathsIbgp.IsNull() { + deletedItems = append(deletedItems, fmt.Sprintf("%v/vrf=%v/ipv4-unicast/maximum-paths/ibgp/max", state.getPath(), strings.Join(stateKeyValues[:], ","))) + } + if !state.Vrfs[i].Ipv4UnicastMaximumPathsEbgp.IsNull() && data.Vrfs[j].Ipv4UnicastMaximumPathsEbgp.IsNull() { + deletedItems = append(deletedItems, fmt.Sprintf("%v/vrf=%v/ipv4-unicast/maximum-paths/ebgp", state.getPath(), strings.Join(stateKeyValues[:], ","))) + } if !state.Vrfs[i].Ipv4UnicastDistanceBgpLocal.IsNull() && data.Vrfs[j].Ipv4UnicastDistanceBgpLocal.IsNull() { deletedItems = append(deletedItems, fmt.Sprintf("%v/vrf=%v/ipv4-unicast/distance/bgp/local", state.getPath(), strings.Join(stateKeyValues[:], ","))) } diff --git a/internal/provider/resource_iosxe_bgp_address_family_ipv4.go b/internal/provider/resource_iosxe_bgp_address_family_ipv4.go index b24abf0c9..28709fed7 100644 --- a/internal/provider/resource_iosxe_bgp_address_family_ipv4.go +++ b/internal/provider/resource_iosxe_bgp_address_family_ipv4.go @@ -240,6 +240,20 @@ func (r *BGPAddressFamilyIPv4Resource) Schema(ctx context.Context, req resource. int64validator.Between(1, 255), }, }, + "ipv4_unicast_maximum_paths_ebgp": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("eBGP-multipath").AddIntegerRangeDescription(1, 32).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1, 32), + }, + }, + "ipv4_unicast_maximum_paths_ibgp": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("iBGP-multipath").AddIntegerRangeDescription(1, 32).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1, 32), + }, + }, }, } } diff --git a/internal/provider/resource_iosxe_bgp_address_family_ipv4_test.go b/internal/provider/resource_iosxe_bgp_address_family_ipv4_test.go index 53ed99c8d..860669c27 100644 --- a/internal/provider/resource_iosxe_bgp_address_family_ipv4_test.go +++ b/internal/provider/resource_iosxe_bgp_address_family_ipv4_test.go @@ -52,6 +52,8 @@ func TestAccIosxeBGPAddressFamilyIPv4(t *testing.T) { checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_address_family_ipv4.test", "ipv4_unicast_distance_bgp_external", "20")) checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_address_family_ipv4.test", "ipv4_unicast_distance_bgp_internal", "200")) checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_address_family_ipv4.test", "ipv4_unicast_distance_bgp_local", "200")) + checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_address_family_ipv4.test", "ipv4_unicast_maximum_paths_ebgp", "2")) + checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_address_family_ipv4.test", "ipv4_unicast_maximum_paths_ibgp", "2")) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, @@ -148,6 +150,8 @@ func testAccIosxeBGPAddressFamilyIPv4Config_all() string { config += ` ipv4_unicast_distance_bgp_external = 20` + "\n" config += ` ipv4_unicast_distance_bgp_internal = 200` + "\n" config += ` ipv4_unicast_distance_bgp_local = 200` + "\n" + config += ` ipv4_unicast_maximum_paths_ebgp = 2` + "\n" + config += ` ipv4_unicast_maximum_paths_ibgp = 2` + "\n" config += ` depends_on = [iosxe_restconf.PreReq0, ]` + "\n" config += `}` + "\n" return config diff --git a/internal/provider/resource_iosxe_bgp_address_family_ipv4_vrf.go b/internal/provider/resource_iosxe_bgp_address_family_ipv4_vrf.go index 0afc9058a..8fd421313 100644 --- a/internal/provider/resource_iosxe_bgp_address_family_ipv4_vrf.go +++ b/internal/provider/resource_iosxe_bgp_address_family_ipv4_vrf.go @@ -275,6 +275,20 @@ func (r *BGPAddressFamilyIPv4VRFResource) Schema(ctx context.Context, req resour int64validator.Between(1, 255), }, }, + "ipv4_unicast_maximum_paths_ebgp": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("eBGP-multipath").AddIntegerRangeDescription(1, 32).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1, 32), + }, + }, + "ipv4_unicast_maximum_paths_ibgp": schema.Int64Attribute{ + MarkdownDescription: helpers.NewAttributeDescription("").AddIntegerRangeDescription(1, 32).String, + Optional: true, + Validators: []validator.Int64{ + int64validator.Between(1, 32), + }, + }, }, }, }, diff --git a/internal/provider/resource_iosxe_bgp_address_family_ipv4_vrf_test.go b/internal/provider/resource_iosxe_bgp_address_family_ipv4_vrf_test.go index 61e6bcf1b..82db2c723 100644 --- a/internal/provider/resource_iosxe_bgp_address_family_ipv4_vrf_test.go +++ b/internal/provider/resource_iosxe_bgp_address_family_ipv4_vrf_test.go @@ -39,7 +39,6 @@ func TestAccIosxeBGPAddressFamilyIPv4VRF(t *testing.T) { checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_advertise_l2vpn_evpn", "true")) checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_redistribute_connected", "true")) checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_router_id_loopback", "101")) - checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_router_id_ip", "10.1.1.1")) checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_aggregate_addresses.0.ipv4_address", "50.0.0.0")) checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_aggregate_addresses.0.ipv4_mask", "255.255.0.0")) checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_redistribute_static", "true")) @@ -56,6 +55,8 @@ func TestAccIosxeBGPAddressFamilyIPv4VRF(t *testing.T) { checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_distance_bgp_external", "20")) checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_distance_bgp_internal", "200")) checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_distance_bgp_local", "200")) + checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_maximum_paths_ebgp", "2")) + checks = append(checks, resource.TestCheckResourceAttr("iosxe_bgp_address_family_ipv4_vrf.test", "vrfs.0.ipv4_unicast_maximum_paths_ibgp", "2")) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, @@ -151,7 +152,6 @@ func testAccIosxeBGPAddressFamilyIPv4VRFConfig_all() string { config += ` ipv4_unicast_advertise_l2vpn_evpn = true` + "\n" config += ` ipv4_unicast_redistribute_connected = true` + "\n" config += ` ipv4_unicast_router_id_loopback = 101` + "\n" - config += ` ipv4_unicast_router_id_ip = "10.1.1.1"` + "\n" config += ` ipv4_unicast_aggregate_addresses = [{` + "\n" config += ` ipv4_address = "50.0.0.0"` + "\n" config += ` ipv4_mask = "255.255.0.0"` + "\n" @@ -176,6 +176,8 @@ func testAccIosxeBGPAddressFamilyIPv4VRFConfig_all() string { config += ` ipv4_unicast_distance_bgp_external = 20` + "\n" config += ` ipv4_unicast_distance_bgp_internal = 200` + "\n" config += ` ipv4_unicast_distance_bgp_local = 200` + "\n" + config += ` ipv4_unicast_maximum_paths_ebgp = 2` + "\n" + config += ` ipv4_unicast_maximum_paths_ibgp = 2` + "\n" config += ` }]` + "\n" config += ` depends_on = [iosxe_restconf.PreReq0, iosxe_restconf.PreReq1, iosxe_restconf.PreReq2, ]` + "\n" config += `}` + "\n" diff --git a/templates/guides/changelog.md.tmpl b/templates/guides/changelog.md.tmpl index 3db265d5a..d0d7624c4 100644 --- a/templates/guides/changelog.md.tmpl +++ b/templates/guides/changelog.md.tmpl @@ -15,6 +15,7 @@ description: |- - Add `evpn_ethernet_segments` attribute to `iosxe_interface_ethernet` and `iosxe_interface_port_channel` resources and data sources - Add `set_ip_next_hop_unchanged` attribute to `iosxe_route_map` resource and data source - Enhance `set_communities` attribute documentation in `iosxe_route_map` to clarify support for well-known BGP community values (internet, local-AS, no-advertise, no-export, gshut) +- Add support for maximum-path (ebgp and ibgp) for BGP ipv4 unicast with VRF ## 0.9.3 @@ -29,7 +30,7 @@ description: |- - Add `passive_interface_disable_*` attributes to `iosxe_ospf` and `iosxe_ospf_vrf` resources and data sources - Fix issue with destroying `iosxe_interface_ethernet` resources - Change route target attributes of `iosxe_vrf` from type "List" to "Set" -- Add `role_based_enforcement` attributes to `iosxe_cts` +- Add `role_based_enforcement` attributes to `iosxe_cts` - Add `tftp_source_interface_*` attributes to `iosxe_system` resource and data source - Add `hash` attribute to `iosxe_crypto_pki` resource and data source - Add `snooping_information_option`, `snooping_information_option_allow_untrusted` and `snooping_information_option_format_remote_id_string` attributes to `iosxe_dhcp` resource and data source @@ -74,7 +75,7 @@ description: |- - Add `level`, `list_name`, `action_type`, `broadcast`, `group_broadcast`, `group_logger`, `group1_group`, `group2_group`, `group3_group`, `group4_group`, `name`, `default`, `none`, `start_stop_broadcast`, `start_stop_logger`, `start_stop_group1`, `start_stop_group2`, `start_stop_group3`, `start_stop_group4`, `stop_only_broadcast`, `stop_only_logger`, `stop_only_group1`, `stop_only_group2`, `stop_only_group3`, `stop_only_group4`, `wait_start_broadcast`, `wait_start_logger`, `wait_start_group1`, `wait_start_group2`, `wait_start_group3`, `wait_start_group4`, `name`, `none`, `start_stop_broadcast`, `start_stop_logger`, `start_stop_group1`, `start_stop_group2`, `start_stop_group3`, `start_stop_group4`, `stop_only_broadcast`, `stop_only_logger`, `stop_only_group1`, `stop_only_group2`, `stop_only_group3`, `stop_only_group4`, `wait_start_broadcast`, `wait_start_logger`, `wait_start_group1`, `wait_start_group2`, `wait_start_group3`, and `wait_start_group4` attributes to `iosxe_aaa_accounting` resource and data source - Add `enable_default_group1_cache`, `enable_default_group1_enable`, `enable_default_group1_group`, `enable_default_group1_line`, `enable_default_group1_none`, `enable_default_group2_cache`, `enable_default_group2_enable`, `enable_default_group2_group`, `enable_default_group2_line`, `enable_default_group2_none`, `enable_default_group3_cache`, `enable_default_group3_enable`, `enable_default_group3_group`, `enable_default_group3_line`, `enable_default_group3_none`, `enable_default_group4_cache`, `enable_default_group4_enable`, `enable_default_group4_group`, `enable_default_group4_line`, and `enable_default_group4_none` attributes to `iosxe_aaa_authentication` resource and data source - Add `level`, `list_name`, `a1_group`, `a1_local`, `a1_if_authenticated`, `a1_none`, `a1_radius`, `a1_tacacs`, `a2_group`, `a2_local`, `a2_if_authenticated`, `a2_none`, `a2_radius`, `a2_tacacs`, `a3_group`, `a3_local`, `a3_if_authenticated`, `a3_none`, `a3_radius`, `a3_tacacs`, `a4_group`, `a4_local`, `a4_if_authenticated`, `a4_none`, `a4_radius`, `a4_tacacs`, `name`, `group1_cache`, `group1_group`, `group1_radius`, and `group1_tacacs` attributes to `iosxe_aaa_authorization` resource and data source -- Add `vrf`, `local_authentication_type`, `local_authorization`, and `local_auth_max_fail_attempts` attributes to `iosxe_aaa` resrouce and data source +- Add `vrf`, `local_authentication_type`, `local_authorization`, and `local_auth_max_fail_attempts` attributes to `iosxe_aaa` resrouce and data source - Add `icmp_named_msg_type`, `destination_port_equal_2`, `destination_port_equal_3`, `destination_port_equal_4`, `destination_port_equal_5`, `destination_port_equal_6`, `destination_port_equal_7`, `destination_port_equal_8`, `destination_port_equal_9`, `destination_port_equal_10`, `icmp_msg_type`, and `icmp_msg_code` attributes to `iosxe_access_list_extended` resource and data source - Add `iosxe_access_list_role_based` resource and data source - Add `filter_lists_cdp` attribute to `iosxe_device_sensor` resource and data source From 3600b0e22f2f4b3173c1356de632729547ff0177 Mon Sep 17 00:00:00 2001 From: Jeremy Spencer Date: Wed, 5 Nov 2025 19:20:53 -0500 Subject: [PATCH 2/2] chore: update CHANGELOG.md per request --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99485aed9..348396caf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ - Add `evpn_ethernet_segments` attribute to `iosxe_interface_ethernet` and `iosxe_interface_port_channel` resources and data sources - Add `set_ip_next_hop_unchanged` attribute to `iosxe_route_map` resource and data source - Enhance `set_communities` attribute documentation in `iosxe_route_map` to clarify support for well-known BGP community values (internet, local-AS, no-advertise, no-export, gshut) -- Add support for maximum-path (ebgp and ibgp) for BGP ipv4 unicast with VRF +- Add `ipv4_unicast_maximum_paths_ebgp` and `ipv4_unicast_maximum_paths_ibgp` attributes to the `iosxe_bgp_address_family_ipv4` resource and `iosxe_bgp_address_family_ipv4` resource ## 0.9.3