Skip to content

Commit

Permalink
Refactor: Remove ties to overlay_address_families for WAN
Browse files Browse the repository at this point in the history
  • Loading branch information
gmuloc committed Jan 24, 2025
1 parent 6ae4f85 commit 41ca88b
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 30 deletions.
2 changes: 1 addition & 1 deletion python-avd/pyavd/_eos_designs/shared_utils/routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def overlay_routing_protocol(self: SharedUtils) -> str:

@cached_property
def overlay_address_families(self: SharedUtils) -> list[str]:
if self.overlay_routing_protocol in ["ebgp", "ibgp"] or self.is_wan_router:
if self.overlay_routing_protocol in ["ebgp", "ibgp"]:
default_overlay_address_families = self.node_type_key_data.default_overlay_address_families
return self.node_config.overlay_address_families._as_list() or default_overlay_address_families._as_list()
return []
Expand Down
15 changes: 13 additions & 2 deletions python-avd/pyavd/_eos_designs/shared_utils/wan.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,17 @@ def wan_stun_dtls_profile_name(self: SharedUtils) -> str | None:

def vrf_wan_vni(self: SharedUtils, vrf_name: str) -> int | None:
"""Returns the VRF WAN VNI or None."""
if vrf_name not in self.inputs.wan_virtual_topologies.vrfs:
if vrf_name not in self._filtered_wan_vrfs:
return None
return self.inputs.wan_virtual_topologies.vrfs[vrf_name].wan_vni
return self._filtered_wan_vrfs[vrf_name].wan_vni

@cached_property
def _filtered_wan_vrfs(self: AvdStructuredConfigNetworkServices) -> EosDesigns.WanVirtualTopologies.Vrfs:
"""Loop through all the VRFs defined under `wan_virtual_topologies.vrfs` and returns a list of mode."""
wan_vrfs = EosDesigns.WanVirtualTopologies.Vrfs(vrf for vrf in self.inputs.wan_virtual_topologies.vrfs if vrf.name in self.vrfs or self.is_wan_server)

# Check that default is in the list as it is required everywhere
if "default" not in wan_vrfs:
wan_vrfs.append(EosDesigns.WanVirtualTopologies.VrfsItem(name="default", wan_vni=1))

return wan_vrfs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def _cv_pathfinder_wan_vrfs(self: AvdStructuredConfigNetworkServices) -> list:
# For CV Pathfinder, it is required to go through all the AVT profiles in the policy to assign an ID.
wan_vrfs = []

for vrf in self._filtered_wan_vrfs:
for vrf in self.shared_utils._filtered_wan_vrfs:
wan_vrf = {"name": vrf.name, "policy": f"{vrf.policy}-WITH-CP" if vrf.name == "default" else vrf.policy, "profiles": []}

# Need to allocate an ID for each profile in the policy, for now picked up from the input.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,18 +150,19 @@ def _router_bgp_vrfs(self: AvdStructuredConfigNetworkServices) -> dict:
continue

vrf_name = vrf.name
bgp_vrf = strip_empties_from_dict(
{
"eos_cli": vrf.bgp.raw_eos_cli,
}
)
bgp_vrf = {
"name": vrf.name,
"eos_cli": vrf.bgp.raw_eos_cli,
}

if vrf.bgp.structured_config:
self.custom_structured_configs.nested.router_bgp.vrfs.obtain(vrf_name)._deepmerge(
vrf.bgp.structured_config, list_merge=self.custom_structured_configs.list_merge_strategy
)

if vrf_address_families := [af for af in vrf.address_families if af in self.shared_utils.overlay_address_families]:
if (
vrf_address_families := [af for af in vrf.address_families if af in self.shared_utils.overlay_address_families]
) or self.shared_utils.vrf_wan_vni(vrf_name) is not None:
# The called function in-place updates the bgp_vrf dict.
self._update_router_bgp_vrf_evpn_or_mpls_cfg(bgp_vrf, vrf, vrf_address_families)

Expand Down Expand Up @@ -269,7 +270,7 @@ def _router_bgp_vrfs(self: AvdStructuredConfigNetworkServices) -> dict:
append_if_not_duplicate(
list_of_dicts=router_bgp["vrfs"],
primary_key="name",
new_dict={"name": vrf_name, **bgp_vrf},
new_dict=bgp_vrf,
context="BGP VRFs defined under network services",
context_keys=["name"],
)
Expand All @@ -287,6 +288,18 @@ def _update_router_bgp_vrf_evpn_or_mpls_cfg(
vrf_rt = self.get_vrf_rt(vrf)
route_targets = {"import": [], "export": []}

# if "evpn" in vrf_address_families the RTs will be added
if self.shared_utils.vrf_wan_vni(bgp_vrf["name"]) and "evpn" not in vrf_address_families:
if (target := get_item(route_targets["import"], "address_family", "evpn")) is None:
route_targets["import"].append({"address_family": "evpn", "route_targets": [vrf_rt]})
else:
target["route_targets"].append(vrf_rt)

if (target := get_item(route_targets["export"], "address_family", "evpn")) is None:
route_targets["export"].append({"address_family": "evpn", "route_targets": [vrf_rt]})
else:
target["route_targets"].append(vrf_rt)

for af in vrf_address_families:
if (target := get_item(route_targets["import"], "address_family", af)) is None:
route_targets["import"].append({"address_family": af, "route_targets": [vrf_rt]})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ def router_path_selection(self: AvdStructuredConfigNetworkServices) -> dict | No
# for AutoVPN, need also vrfs and policies.
if self.inputs.wan_mode == "autovpn":
vrfs = [
{"name": vrf.name, "path_selection_policy": f"{vrf.policy}-WITH-CP" if vrf.name == "default" else vrf.policy} for vrf in self._filtered_wan_vrfs
{"name": vrf.name, "path_selection_policy": f"{vrf.policy}-WITH-CP" if vrf.name == "default" else vrf.policy}
for vrf in self.shared_utils._filtered_wan_vrfs
]

router_path_selection.update(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,6 @@ class UtilsWanMixin:
Class should only be used as Mixin to a AvdStructuredConfig class.
"""

@cached_property
def _filtered_wan_vrfs(self: AvdStructuredConfigNetworkServices) -> EosDesigns.WanVirtualTopologies.Vrfs:
"""Loop through all the VRFs defined under `wan_virtual_topologies.vrfs` and returns a list of mode."""
wan_vrfs = EosDesigns.WanVirtualTopologies.Vrfs(
vrf for vrf in self.inputs.wan_virtual_topologies.vrfs if vrf.name in self.shared_utils.vrfs or self.shared_utils.is_wan_server
)

# Check that default is in the list as it is required everywhere
if "default" not in wan_vrfs:
wan_vrfs.append(EosDesigns.WanVirtualTopologies.VrfsItem(name="default", wan_vni=1))

return wan_vrfs

@cached_property
def _wan_virtual_topologies_policies(self: AvdStructuredConfigNetworkServices) -> EosDesigns.WanVirtualTopologies.Policies:
"""This function parses the input data and append the default-policy if not already present."""
Expand All @@ -62,7 +49,7 @@ def _filtered_wan_policies(self: AvdStructuredConfigNetworkServices) -> list:
filtered_policy_names = []
filtered_policies = []

for vrf in self._filtered_wan_vrfs:
for vrf in self.shared_utils._filtered_wan_vrfs:
# Need to handle VRF default differently and lookup for the original policy
if vrf.policy not in self._wan_virtual_topologies_policies:
msg = (
Expand Down Expand Up @@ -401,7 +388,7 @@ def _wan_control_plane_virtual_topology(self: AvdStructuredConfigNetworkServices
@cached_property
def _wan_control_plane_profile_name(self: AvdStructuredConfigNetworkServices) -> str:
"""Control plane profile name."""
vrf_default_policy_name = self._filtered_wan_vrfs["default"].policy
vrf_default_policy_name = self.shared_utils._filtered_wan_vrfs["default"].policy
return self._wan_control_plane_virtual_topology.name or f"{vrf_default_policy_name}-CONTROL-PLANE"

@cached_property
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def vxlan_interface(self: AvdStructuredConfigNetworkServices) -> dict | None:

if self.shared_utils.is_wan_server:
# loop through wan_vrfs and add VRF VNI if not present
for vrf in self._filtered_wan_vrfs:
for vrf in self.shared_utils._filtered_wan_vrfs:
# Duplicate check is not done on the actual list of vlans, but instead on our local "vnis" list.
# This is necessary to find duplicate VNIs across multiple object types.
vrf_data = {"name": vrf.name, "vni": vrf.wan_vni}
Expand Down Expand Up @@ -163,15 +163,15 @@ def _get_vxlan_interface_config_for_vrf(

if self.shared_utils.is_wan_router:
# Every VRF with EVPN on a WAN router must have a wan_vni defined.
if vrf_name not in self._filtered_wan_vrfs:
if vrf_name not in self.shared_utils._filtered_wan_vrfs:
msg = (
f"The VRF '{vrf_name}' does not have a `wan_vni` defined under 'wan_virtual_topologies'. "
"If this VRF was not intended to be extended over the WAN, but still required to be configured on the WAN router, "
"set 'address_families: []' under the VRF definition. If this VRF was not intended to be configured on the WAN router, "
"use the VRF filter 'deny_vrfs' under the node settings."
)
raise AristaAvdInvalidInputsError(msg)
vni = self._filtered_wan_vrfs[vrf_name].wan_vni
vni = self.shared_utils._filtered_wan_vrfs[vrf_name].wan_vni
else:
vni = default(vrf.vrf_vni, vrf.vrf_id)

Expand Down

0 comments on commit 41ca88b

Please sign in to comment.