Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cumulus NVUE: Support VRF route leaking #1976

Merged
merged 2 commits into from
Feb 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/caveats.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,8 @@ defaults.devices.cumulus.libvirt.memory: 2048
Other caveats:

* The default MTU value is 1500 to match the implementation defaults from other vendors and enable things like seamless OSPF peering.
* Older Cumulus Linux releases (up to at least 5.9.2) do not support asymmetrical IRB over VXLAN.
* *netlab* uses Cumulus VX 5.3 containers created by Michael Kashin and downloaded from his Docker Hub account. These containers are severely out-of-date, are not tested in our integration tests, and might not work as expected.
* Some features - such as VRF route leaking and route advertisement in the default VRF (used in certain EVPN scenarios) - are not supported by NVUE, and require the use of custom config *snippets*. Only one such snippet is supported per configuration file (e.g. /etc/frr/frr.conf), which means a topology using a combination of multiple features that all require *snippets* will not work.

(caveats-os10)=
## Dell OS10
Expand Down
2 changes: 1 addition & 1 deletion docs/module/vrf.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ VRFs are supported on these platforms:
| Cisco IOS XE[^18v] | ✅ | ✅ | ✅ |
| Cisco Nexus OS | ✅ | ✅ | ✅ |
| Cumulus Linux 4.x | ✅ | ✅ | ✅ |
| Cumulus 5.x (NVUE) | ✅ | | ✅ |
| Cumulus 5.x (NVUE) | ✅ | ✅ [❗](caveats-cumulus-nvue) | ✅ |
| Dell OS10 | ✅ | ✅ | ✅ |
| FRR [❗](caveats-frr) | ✅ | ✅ | ✅ |
| Junos[^Junos] | ✅ | ✅ | ✅ |
Expand Down
9 changes: 8 additions & 1 deletion netsim/ansible/templates/bgp/cumulus_nvue.j2
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
{% from "bgp/cumulus_nvue.macro.j2" import bgp_in_vrf with context %}
---
- set:
router:
bgp:
enable: on
autonomous-system: {{ bgp.as }}
{% if bgp.router_id|ipv4 %}
router-id: {{ bgp.router_id }}
{% endif %}
{{ bgp_in_vrf('default', { 'bgp': bgp, 'loopback': loopback, 'af': af } ) }}
6 changes: 3 additions & 3 deletions netsim/ansible/templates/bgp/cumulus_nvue.macro.j2
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
enable: on
autonomous-system: {{ bgp.as }}
router-id: {{ vrf_bgp.router_id|default(bgp.router_id) }}
{% if vrf_bgp.rd is defined %}
rd: {{ vrf_bgp.rd }}
{% if vrf.rd is defined %}
rd: {{ vrf.rd }}
{% endif %}
{% if vrf_bgp.rr|default(False) %}
route-reflection:
Expand All @@ -32,7 +32,7 @@
{{ af }}-unicast:
enable: on
{{ redistribute.config(vrf_bgp,af=af)|indent(16,first=True) }}
{% set _loopback = [ vrf.loopback[af] ] if vrf.loopback[af] is defined and vrf_bgp.advertise_loopback else [] %}
{% set _loopback = [ vrf.loopback[af] ] if vrf.loopback[af] is defined and bgp.advertise_loopback|default(True) else [] %}
{% set data = namespace(networks=_loopback) %}
{% for l in interfaces|default([]) if l.bgp.advertise|default("") and l[af] is defined and l.vrf|default('default')==vrf_name %}
{% set data.networks = data.networks + [ l[af] ] %}
Expand Down
30 changes: 29 additions & 1 deletion netsim/ansible/templates/vrf/cumulus_nvue.j2
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{% from "ospf/cumulus_nvue.j2" import vrf_ospf with context %}
{% from "bgp/cumulus_nvue.macro.j2" import bgp_in_vrf with context %}

---
- set:
vrf:
{% for vname,vdata in vrfs.items() %}
Expand All @@ -15,9 +15,37 @@
{% endfor %}

{% for vname,vdata in vrfs.items() if 'bgp' in vdata %}
{% if loop.first and 'bgp' not in module %}
{# In case the vrf module is used without the bgp module, need to repeat the base router config #}
{% include "bgp/cumulus_nvue.j2" %}
{% endif %}
{{ bgp_in_vrf(vname, vdata) }}
{% endfor %}

{# Workaround for lack of NVUE support for VRF route leaking - note can only create 1 snippet for frr.conf globally #}
{% set import_lengths = vrfs.values()|map(attribute='import',default=[])|map('length')|list %}
{% if import_lengths|max > 1 %}
- set:
system:
config:
snippet:
frr.conf: |
{% for vname,vdata in vrfs.items() %}
router bgp {{ bgp.as }} vrf {{ vname }}
{% for _af in ['ipv4','ipv6'] if _af in vdata.af %}
address-family {{ _af }} unicast
label vpn export auto
export vpn
import vpn
rd vpn export {{ vdata.rd }}
rt vpn import {{ vdata.import|join(" ") }}
rt vpn export {{ vdata.export|join(" ") }}
exit-address-family
{% endfor %}
!
{% endfor %}
{% endif %}

{% for intf in netlab_interfaces if intf.vrf is defined %}
- set:
{% if intf.type=='loopback' %}
Expand Down
16 changes: 0 additions & 16 deletions netsim/devices/cumulus_nvue.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,6 @@ def nvue_check_stp_features(node: Box, topology: Box) -> None:
more_data=err_data,
node=node)

"""
Checks for vrf route leaking usage which is not yet implemented
"""
def nvue_check_vrf_route_leaking(node: Box) -> None:
for vname,vdata in node.get("vrfs",{}).items():
if len(vdata.get('export',[]))>1 or len(vdata.get('import',[]))>1:
log.error(f"Topology uses vrf route leaking which Netlab does not implement (yet) for Cumulus NVUE node '{node.name}'",
category=log.FatalError,
module='vrf',
hint='route leaking')
return

"""
Checks for OSPFv3 which is not supported by NVUE configuration command
"""
Expand Down Expand Up @@ -174,12 +162,8 @@ def device_quirks(self, node: Box, topology: Box) -> None:
nvue_check_ospfv3(node)
nvue_merge_ospf_loopbacks(node)

# NVUE specific quirks
if 'stp' in mods:
nvue_check_stp_features(node,topology)

if 'vrf' in mods:
nvue_check_vrf_route_leaking(node)

if 'vxlan' in mods:
mark_shared_mlag_vtep(node,topology)
Expand Down