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: BGP in VRFs #1972

Merged
merged 8 commits into from
Feb 23, 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/module/vrf.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ These platforms support routing protocols in VRFs:
| Cisco IOS XE[^18v] | ✅ [❗](caveats-csr) | ✅ | ✅ | ✅ | ✅ |
| Cisco Nexus OS | ✅ | ❌ | ✅ |
| Cumulus Linux 4.x | ✅ | ❌ | ✅ | ✅ | ✅ |
| Cumulus 5.x (NVUE) | ✅ | ❌ | | ❌ | ❌ |
| Cumulus 5.x (NVUE) | ✅ | ❌ | | ❌ | ❌ |
| Dell OS10 | ✅ | ❌ | ✅ |
| FRR [❗](caveats-frr) | ✅ | ✅ | ✅ | ✅ | ✅ |
| Junos[^Junos] | ✅ | ✅ | ✅ |
Expand Down
117 changes: 3 additions & 114 deletions netsim/ansible/templates/bgp/cumulus_nvue.j2
Original file line number Diff line number Diff line change
@@ -1,114 +1,3 @@
{% import "templates/routing/_redistribute.cumulus_nvue.j2" as redistribute with context %}
{% macro advertise_communities(comms) %}
community-advertise:
{% for c in ['standard', 'extended', 'large'] %}
{{ c.replace("standard","regular") }}: {{ 'on' if c in comms else 'off' }}
{% endfor %}
{% endmacro %}

- set:
router:
bgp:
enable: on
vrf:
default:
router:
bgp:
{% if bgp.rr|default(False) %}
route-reflection:
enable: on
{% if bgp.rr_cluster_id is defined %}
cluster-id: {{ bgp.rr_cluster_id }}
{% endif %}
{% endif %}
{% for af in ['ipv4','ipv6'] if bgp[af] is defined %}
{% if loop.first %}
address-family:
{% endif %}
{{ af }}-unicast:
enable: on
{{ redistribute.config(bgp,af=af)|indent(16,first=True) }}
{% set _loopback = [ loopback[af] ] if loopback[af] is defined and bgp.advertise_loopback else [] %}
{% set data = namespace(networks=_loopback) %}
{% for l in interfaces|default([]) if l.bgp.advertise|default("") and l[af] is defined and not 'vrf' in l %}
{% set data.networks = data.networks + [ l[af] ] %}
{% endfor %}
{% for pfx in bgp.originate|default([]) if af == 'ipv4' %}
{% set data.networks = data.networks + [ pfx ] %}
{% endfor %}
{% if data.networks!=[] %}
network:
{% for pfx in data.networks %}
{{ pfx|ipaddr('0') }}: {}
{% endfor %}
{% endif %}
{% endfor %}
autonomous-system: {{ bgp.as }}
{% for n in bgp.neighbors %}
{% if loop.first %}
neighbor:
{% endif %}
{% if n.local_if is defined %}
{{ n.local_if }}:
type: unnumbered
remote-as: {{ n.as }}
address-family:
ipv4-unicast:
enable: {{ 'on' if n.ipv4_rfc8950|default(False) else 'off' }}
community-advertise:
extended: on
ipv6-unicast:
enable: {{ 'on' if n.ipv6|default(False) and n.activate.ipv6|default(False) else 'off' }}
community-advertise:
extended: on
{% endif %}
{% for af in ('ipv4','ipv6') if af in n and n[af] is string %}
{{ n[af] }}:
description: "{{ n.name }}"
{% if n._source_ifname is defined %}
update-source: {{ n._source_ifname }}
{% endif %}
remote-as: {{ 'internal' if n.as==bgp.as else n.as }}
{% if n.local_as is defined %}
local-as:
asn: {{ n.local_as }}
enable: on
{% if n.replace_global_as|default(True) %}
replace: on
prepend: off
{% endif %}
{% endif %}
address-family:
{# NVUE cannot turn off default IPv4 activation, so we have to implement a fix for IPv6 #}
{% if af == 'ipv6' %}
ipv4-unicast:
enable: off
{% endif %}
{{ af }}-unicast:
enable: {{ 'on' if n.activate[af]|default(False) else 'off' }}
{% if 'ibgp' in n.type %}
{% if bgp.next_hop_self|default(False) %}
nexthop-setting: self
{% endif %}
{% if bgp.rr|default('') and not n.rr|default('') %}
route-reflector-client: on
{% endif %}
{% endif %}
{% if n.type in bgp.community|default({}) %}
{{ advertise_communities( bgp.community[n.type] ) }}
{% endif %}
{% endfor %}
{% endfor %}
{% if 'router_id' in bgp %}
router-id: {{ bgp.router_id }}
{% endif %}
{% if bgp.originate is defined %}
static:
{% for pfx in bgp.originate|default([]) %}
{{ pfx|ipaddr('0') }}:
address-family: ipv4-unicast
via:
blackhole:
type: blackhole
{% endfor %}
{% endif %}
{% from "bgp/cumulus_nvue.macro.j2" import bgp_in_vrf with context %}
---
{{ bgp_in_vrf('default', { 'bgp': bgp, 'loopback': loopback, 'af': af } ) }}
115 changes: 115 additions & 0 deletions netsim/ansible/templates/bgp/cumulus_nvue.macro.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
{% import "templates/routing/_redistribute.cumulus_nvue.j2" as redistribute with context %}
{% macro advertise_communities(comms) %}
community-advertise:
{% for c in ['standard', 'extended', 'large'] %}
{{ c.replace("standard","regular") }}: {{ 'on' if c in comms else 'off' }}
{% endfor %}
{% endmacro %}
{% macro bgp_in_vrf(vrf_name,vrf) %}
{% set vrf_bgp = vrf.bgp %}
- set:
vrf:
{{ vrf_name }}:
router:
bgp:
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 }}
{% endif %}
{% if vrf_bgp.rr|default(False) %}
route-reflection:
enable: on
{% if vrf_bgp.rr_cluster_id is defined %}
cluster-id: {{ vrf_bgp.rr_cluster_id }}
{% endif %}
{% endif %}
{% for af in ['ipv4','ipv6'] if vrf.af[af] is defined %}
{% if loop.first %}
address-family:
{% endif %}
{{ 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 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] ] %}
{% endfor %}
{% for pfx in vrf_bgp.originate|default([]) if af == 'ipv4' %}
{% set data.networks = data.networks + [ pfx ] %}
{% endfor %}
{% if data.networks!=[] %}
network:
{% for pfx in data.networks %}
{{ pfx|ipaddr('0') }}: {}
{% endfor %}
{% endif %}
{% endfor %}
{% for n in vrf_bgp.neighbors|default([]) %}
{% if loop.first %}
neighbor:
{% endif %}
{% if n.local_if is defined %}
{{ n.local_if }}:
type: unnumbered
remote-as: {{ n.as }}
address-family:
ipv4-unicast:
enable: {{ 'on' if n.ipv4_rfc8950|default(False) else 'off' }}
community-advertise:
extended: on
ipv6-unicast:
enable: {{ 'on' if n.ipv6|default(False) and ('activate' not in n or n.activate.ipv6|default(False)) else 'off' }}
community-advertise:
extended: on
{% endif %}
{% for af in ('ipv4','ipv6') if af in n and n[af] is string %}
{{ n[af] }}:
description: "{{ n.name }}"
{% if n._source_ifname is defined %}
update-source: {{ n._source_ifname }}
{% endif %}
remote-as: {{ 'internal' if n.as==bgp.as else n.as }}
{% if n.local_as is defined %}
local-as:
asn: {{ n.local_as }}
enable: on
{% if n.replace_global_as|default(True) %}
replace: on
prepend: off
{% endif %}
{% endif %}
address-family:
{# NVUE cannot turn off default IPv4 activation, so we have to implement a fix for IPv6 #}
{% if af == 'ipv6' %}
ipv4-unicast:
enable: off
{% endif %}
{{ af }}-unicast:
enable: {{ 'on' if 'activate' not in n or n.activate[af]|default(False) else 'off' }}
{% if 'ibgp' in n.type %}
{% if vrf_bgp.next_hop_self|default(False) %}
nexthop-setting: self
{% endif %}
{% if vrf_bgp.rr|default('') and not n.rr|default('') %}
route-reflector-client: on
{% endif %}
{% endif %}
{% if n.type in vrf_bgp.community|default({}) %}
{{ advertise_communities( vrf_bgp.community[n.type] ) }}
{% endif %}
{% endfor %}
{% endfor %}
{% if vrf_bgp.originate is defined %}
static:
{% for pfx in vrf_bgp.originate|default([]) %}
{{ pfx|ipaddr('0') }}:
address-family: ipv4-unicast
via:
blackhole:
type: blackhole
{% endfor %}
{% endif %}
{% endmacro %}
11 changes: 0 additions & 11 deletions netsim/ansible/templates/evpn/cumulus_nvue.j2
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,6 @@
{% endif %}
router:
bgp:
autonomous-system: {{ vdata.as|default(bgp.as) }}
enable: on
rd: {{ vdata.rd }}
route-export:
to-evpn:
Expand All @@ -115,15 +113,6 @@
route-export:
to-evpn:
enable: on
{# This part belongs in the VRF or BGP template, to be moved #}
enable: on
redistribute:
connected:
enable: on
{% if 'ospf' in vdata %}
ospf:
enable: on
{% endif %}
{% endfor %}
{% endfor %}
{% endif %}
7 changes: 6 additions & 1 deletion netsim/ansible/templates/vrf/cumulus_nvue.j2
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{% from "ospf/cumulus_nvue.j2" import vrf_ospf with context %}
{% from "bgp/cumulus_nvue.macro.j2" import bgp_in_vrf with context %}

- set:
vrf:
Expand All @@ -9,10 +10,14 @@

{% for vname,vdata in vrfs.items() if 'ospf' in vdata %}
{% if vdata.af.ipv4|default(False) %}
{{ vrf_ospf(vname,vdata) }}
{{ vrf_ospf(vname,vdata) }}
{% endif %}
{% endfor %}

{% for vname,vdata in vrfs.items() if 'bgp' in vdata %}
{{ bgp_in_vrf(vname, vdata) }}
{% endfor %}

{% for intf in netlab_interfaces if intf.vrf is defined %}
- set:
{% if intf.type=='loopback' %}
Expand Down
3 changes: 2 additions & 1 deletion netsim/devices/cumulus_nvue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ features:
lla: True
bgp:
activate_af: True
import: [ connected, ospf ]
import: [ connected, ospf, vrf ]
ipv6_lla: True
local_as: True
local_as_ibgp: True
Expand Down Expand Up @@ -65,6 +65,7 @@ features:
subif_name: "{ifname}.{vlan.access_id}"
vrf:
ospfv2: True
bgp: True
vxlan: True
# vtep6: true # Waiting for https://github.com/CumulusNetworks/ifupdown2/pull/315
clab:
Expand Down