From 251d9da4f814ce17dbc171b6421e2cab471ecfb7 Mon Sep 17 00:00:00 2001
From: Colin MacGiollaEain <43743234+colinmacgiolla@users.noreply.github.com>
Date: Wed, 30 Oct 2024 10:18:47 +0000
Subject: [PATCH] Feat(eos_cli_config_gen): Expand CLI to support DualEncap MH
EVPN GW requirements (#4613)
---
.../documentation/devices/router-bgp-evpn.md | 15 ++++++++++++++
.../intended/configs/router-bgp-evpn.cfg | 9 +++++++++
.../inventory/host_vars/router-bgp-evpn.yml | 8 ++++++++
.../docs/tables/router-bgp.md | 14 +++++++++++++
.../j2templates/documentation/router-bgp.j2 | 14 +++++++++++++
.../j2templates/eos/router-bgp.j2 | 13 ++++++++++++
.../schema/eos_cli_config_gen.schema.yml | 20 +++++++++++++++++++
.../schema_fragments/router_bgp.schema.yml | 20 +++++++++++++++++++
8 files changed, 113 insertions(+)
diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/router-bgp-evpn.md b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/router-bgp-evpn.md
index 6116cb94039..7e28738025b 100644
--- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/router-bgp-evpn.md
+++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/documentation/devices/router-bgp-evpn.md
@@ -146,9 +146,15 @@ ASN Notation: asplain
| Settings | Value |
| -------- | ----- |
+| Local Domain | 65101:0 |
+| Remote Domain | 65101:1 |
| Remote Domain Peer Groups | EVPN-OVERLAY-PEERS |
| L3 Gateway Configured | True |
| L3 Gateway Inter-domain | True |
+| Local Domain: Ethernet-Segment Identifier | 0011:1111:1111:1111:1111 |
+| Local Domain: Ethernet-Segment import Route-Target | 11:11:11:11:11:11 |
+| Remote Domain: Ethernet-Segment Identifier | 0022:2222:2222:2222:2222 |
+| Remote Domain: Ethernet-Segment import Route-Target | 22:22:22:22:22:22 |
#### Router BGP VLAN Aware Bundles
@@ -325,11 +331,20 @@ router bgp 65101
neighbor 10.100.100.5 activate
neighbor 10.100.100.5 encapsulation mpls
domain identifier 65101:0
+ domain identifier 65101:1 remote
next-hop resolution disabled
neighbor default next-hop-self received-evpn-routes route-type ip-prefix inter-domain
host-flap detection window 10 threshold 1 expiry timeout 3 seconds
layer-2 fec in-place update
route import overlay-index gateway
+ !
+ evpn ethernet-segment domain local
+ identifier 0011:1111:1111:1111:1111
+ route-target import 11:11:11:11:11:11
+ !
+ evpn ethernet-segment domain remote
+ identifier 0022:2222:2222:2222:2222
+ route-target import 22:22:22:22:22:22
!
address-family ipv4
no neighbor EVPN-OVERLAY-PEERS activate
diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/router-bgp-evpn.cfg b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/router-bgp-evpn.cfg
index 83bac4e7634..c2318bc8222 100644
--- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/router-bgp-evpn.cfg
+++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/intended/configs/router-bgp-evpn.cfg
@@ -148,11 +148,20 @@ router bgp 65101
neighbor 10.100.100.5 activate
neighbor 10.100.100.5 encapsulation mpls
domain identifier 65101:0
+ domain identifier 65101:1 remote
next-hop resolution disabled
neighbor default next-hop-self received-evpn-routes route-type ip-prefix inter-domain
host-flap detection window 10 threshold 1 expiry timeout 3 seconds
layer-2 fec in-place update
route import overlay-index gateway
+ !
+ evpn ethernet-segment domain local
+ identifier 0011:1111:1111:1111:1111
+ route-target import 11:11:11:11:11:11
+ !
+ evpn ethernet-segment domain remote
+ identifier 0022:2222:2222:2222:2222
+ route-target import 22:22:22:22:22:22
!
address-family ipv4
no neighbor EVPN-OVERLAY-PEERS activate
diff --git a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/router-bgp-evpn.yml b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/router-bgp-evpn.yml
index a44a1b1234b..d9878868301 100644
--- a/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/router-bgp-evpn.yml
+++ b/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/host_vars/router-bgp-evpn.yml
@@ -122,6 +122,7 @@ router_bgp:
inter_domain: true
encapsulation: path-selection
domain_identifier: "65101:0"
+ domain_identifier_remote: "65101:1"
neighbors:
- ip_address: 10.100.100.1
activate: true
@@ -191,6 +192,13 @@ router_bgp:
- name: TEST-ENCAPSULATION-2
activate: true
encapsulation: path-selection
+ evpn_ethernet_segment:
+ - domain: remote
+ identifier: "0022:2222:2222:2222:2222"
+ route_target_import: "22:22:22:22:22:22"
+ - domain: local
+ identifier: "0011:1111:1111:1111:1111"
+ route_target_import: "11:11:11:11:11:11"
evpn_hostflap_detection:
enabled: true
window: 10
diff --git a/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/router-bgp.md b/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/router-bgp.md
index c24c212e4e3..330c78d14c9 100644
--- a/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/router-bgp.md
+++ b/ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/router-bgp.md
@@ -345,6 +345,7 @@
| [ id_remote](## "router_bgp.vpws.[].pseudowires.[].id_remote") | Integer | | | | Must match id_local on other pe. |
| [ address_family_evpn](## "router_bgp.address_family_evpn") | Dictionary | | | | |
| [ domain_identifier](## "router_bgp.address_family_evpn.domain_identifier") | String | | | | |
+ | [ domain_identifier_remote](## "router_bgp.address_family_evpn.domain_identifier_remote") | String | | | | |
| [ neighbor_default](## "router_bgp.address_family_evpn.neighbor_default") | Dictionary | | | | |
| [ encapsulation](## "router_bgp.address_family_evpn.neighbor_default.encapsulation") | String | | | Valid Values:
- vxlan
- mpls
- path-selection
| Transport encapsulation for neighbor. |
| [ next_hop_self_source_interface](## "router_bgp.address_family_evpn.neighbor_default.next_hop_self_source_interface") | String | | | | Source interface name for MPLS encapsulation. Requires `encapsulation` to be set as `mpls`. |
@@ -409,6 +410,10 @@
| [ layer_2_fec_in_place_update](## "router_bgp.address_family_evpn.layer_2_fec_in_place_update") | Dictionary | | | | BGP layer-2 in-place FEC operation. |
| [ enabled](## "router_bgp.address_family_evpn.layer_2_fec_in_place_update.enabled") | Boolean | Required | | | |
| [ timeout](## "router_bgp.address_family_evpn.layer_2_fec_in_place_update.timeout") | Integer | | | Min: 0
Max: 300 | In-place FEC update tracking timeout in seconds. |
+ | [ evpn_ethernet_segment](## "router_bgp.address_family_evpn.evpn_ethernet_segment") | List, items: Dictionary | | | | |
+ | [ - domain](## "router_bgp.address_family_evpn.evpn_ethernet_segment.[].domain") | String | Required, Unique | | Valid Values:
- all
- local
- remote
| |
+ | [ identifier](## "router_bgp.address_family_evpn.evpn_ethernet_segment.[].identifier") | String | | | | EVPN Ethernet Segment Identifier (Type 1 format). |
+ | [ route_target_import](## "router_bgp.address_family_evpn.evpn_ethernet_segment.[].route_target_import") | String | | | | Low-order 6 bytes of ES-Import Route Target. |
| [ bgp_additional_paths](## "router_bgp.address_family_evpn.bgp_additional_paths") deprecated | Dictionary | | | | BGP additional-paths commands.This key is deprecated. Support will be removed in AVD version 6.0.0. Use bgp.additional_paths instead. |
| [ receive](## "router_bgp.address_family_evpn.bgp_additional_paths.receive") | Boolean | | | | Receive multiple paths. |
| [ send](## "router_bgp.address_family_evpn.bgp_additional_paths.send") | Dictionary | | | | Send multiple paths. |
@@ -2237,6 +2242,7 @@
id_remote:
address_family_evpn:
domain_identifier:
+ domain_identifier_remote:
neighbor_default:
# Transport encapsulation for neighbor.
@@ -2388,6 +2394,14 @@
# In-place FEC update tracking timeout in seconds.
timeout:
+ evpn_ethernet_segment:
+ - domain:
+
+ # EVPN Ethernet Segment Identifier (Type 1 format).
+ identifier:
+
+ # Low-order 6 bytes of ES-Import Route Target.
+ route_target_import:
# BGP additional-paths commands.
# This key is deprecated.
diff --git a/python-avd/pyavd/_eos_cli_config_gen/j2templates/documentation/router-bgp.j2 b/python-avd/pyavd/_eos_cli_config_gen/j2templates/documentation/router-bgp.j2
index e0d1c532c35..ee85ab289c9 100644
--- a/python-avd/pyavd/_eos_cli_config_gen/j2templates/documentation/router-bgp.j2
+++ b/python-avd/pyavd/_eos_cli_config_gen/j2templates/documentation/router-bgp.j2
@@ -645,6 +645,12 @@ ASN Notation: {{ router_bgp.as_notation | arista.avd.default('asplain') }}
| Settings | Value |
| -------- | ----- |
+{% if router_bgp.address_family_evpn.domain_identifier is arista.avd.defined %}
+| Local Domain | {{ router_bgp.address_family_evpn.domain_identifier }} |
+{% endif %}
+{% if router_bgp.address_family_evpn.domain_identifier_remote is arista.avd.defined %}
+| Remote Domain | {{ router_bgp.address_family_evpn.domain_identifier_remote }} |
+{% endif %}
{% if evpn_gw_config.peer_groups | length > 0 %}
| Remote Domain Peer Groups | {{ evpn_gw_config.peer_groups | join(", ") }} |
{% endif %}
@@ -654,6 +660,14 @@ ASN Notation: {{ router_bgp.as_notation | arista.avd.default('asplain') }}
{% if router_bgp.address_family_evpn.neighbor_default.next_hop_self_received_evpn_routes.inter_domain is arista.avd.defined(true) %}
| L3 Gateway Inter-domain | True |
{% endif %}
+{% for segment in router_bgp.address_family_evpn.evpn_ethernet_segment | arista.avd.natural_sort('domain') %}
+{% if segment.identifier is arista.avd.defined %}
+| {{ segment.domain | title }} Domain: Ethernet-Segment Identifier | {{ segment.identifier }} |
+{% endif %}
+{% if segment.route_target_import is arista.avd.defined %}
+| {{ segment.domain | title }} Domain: Ethernet-Segment import Route-Target | {{ segment.route_target_import }} |
+{% endif %}
+{% endfor %}
{% endif %}
{% if router_bgp.address_family_ipv4_labeled_unicast is arista.avd.defined %}
diff --git a/python-avd/pyavd/_eos_cli_config_gen/j2templates/eos/router-bgp.j2 b/python-avd/pyavd/_eos_cli_config_gen/j2templates/eos/router-bgp.j2
index 47e135d2831..2b7724fc4f0 100644
--- a/python-avd/pyavd/_eos_cli_config_gen/j2templates/eos/router-bgp.j2
+++ b/python-avd/pyavd/_eos_cli_config_gen/j2templates/eos/router-bgp.j2
@@ -941,6 +941,9 @@ router bgp {{ router_bgp.as }}
{% if router_bgp.address_family_evpn.domain_identifier is arista.avd.defined %}
domain identifier {{ router_bgp.address_family_evpn.domain_identifier }}
{% endif %}
+{% if router_bgp.address_family_evpn.domain_identifier_remote is arista.avd.defined %}
+ domain identifier {{ router_bgp.address_family_evpn.domain_identifier_remote }} remote
+{% endif %}
{% if router_bgp.address_family_evpn.next_hop.resolution_disabled is arista.avd.defined(true) %}
next-hop resolution disabled
{% endif %}
@@ -981,6 +984,16 @@ router bgp {{ router_bgp.as }}
{% if router_bgp.address_family_evpn.route.import_overlay_index_gateway is arista.avd.defined(true) %}
route import overlay-index gateway
{% endif %}
+{% for segment in router_bgp.address_family_evpn.evpn_ethernet_segment | arista.avd.natural_sort('domain') %}
+ !
+ evpn ethernet-segment domain {{ segment.domain }}
+{% if segment.identifier is arista.avd.defined %}
+ identifier {{ segment.identifier }}
+{% endif %}
+{% if segment.route_target_import is arista.avd.defined %}
+ route-target import {{ segment.route_target_import }}
+{% endif %}
+{% endfor %}
{% endif %}
{# address family flow-spec ipv4 activation #}
{% if router_bgp.address_family_flow_spec_ipv4 is arista.avd.defined %}
diff --git a/python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.schema.yml b/python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.schema.yml
index e0b5760c17b..0c853a01b8c 100644
--- a/python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.schema.yml
+++ b/python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.schema.yml
@@ -13118,6 +13118,8 @@ keys:
keys:
domain_identifier:
type: str
+ domain_identifier_remote:
+ type: str
neighbor_default:
type: dict
keys:
@@ -13331,6 +13333,24 @@ keys:
- str
min: 0
max: 300
+ evpn_ethernet_segment:
+ type: list
+ primary_key: domain
+ items:
+ type: dict
+ keys:
+ domain:
+ type: str
+ valid_values:
+ - all
+ - local
+ - remote
+ identifier:
+ type: str
+ description: EVPN Ethernet Segment Identifier (Type 1 format).
+ route_target_import:
+ type: str
+ description: Low-order 6 bytes of ES-Import Route Target.
bgp_additional_paths:
type: dict
deprecation:
diff --git a/python-avd/pyavd/_eos_cli_config_gen/schema/schema_fragments/router_bgp.schema.yml b/python-avd/pyavd/_eos_cli_config_gen/schema/schema_fragments/router_bgp.schema.yml
index 77237147b3c..0141aef82ae 100644
--- a/python-avd/pyavd/_eos_cli_config_gen/schema/schema_fragments/router_bgp.schema.yml
+++ b/python-avd/pyavd/_eos_cli_config_gen/schema/schema_fragments/router_bgp.schema.yml
@@ -1248,6 +1248,8 @@ keys:
keys:
domain_identifier:
type: str
+ domain_identifier_remote:
+ type: str
neighbor_default:
type: dict
keys:
@@ -1455,6 +1457,24 @@ keys:
- str
min: 0
max: 300
+ evpn_ethernet_segment:
+ type: list
+ primary_key: domain
+ items:
+ type: dict
+ keys:
+ domain:
+ type: str
+ valid_values:
+ - all
+ - local
+ - remote
+ identifier:
+ type: str
+ description: EVPN Ethernet Segment Identifier (Type 1 format).
+ route_target_import:
+ type: str
+ description: Low-order 6 bytes of ES-Import Route Target.
bgp_additional_paths:
type: dict
deprecation: