Skip to content
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
3 changes: 1 addition & 2 deletions docs/caveats.md
Original file line number Diff line number Diff line change
Expand Up @@ -443,8 +443,7 @@ sudo pip3 install --upgrade 'ansible>=9.5.1'

Other caveats:

* In our current implementation, Nokia SR-OS does not propagate EVPN type-5 (IP prefix) routes into VRF routing protocols.
* We did not implement inter-VRF route leaking. Every VRF is limited to one import and export route target (and they have to match).
* We implemented inter-VRF route leaking only for MPLS/VPN deployments.
* The SR OS configuration templates do not support additional routing policies on routing protocol route imports
* An SR OS interface cannot use an unnumbered IPv4 address in combination with IPv6 GUA
* SR OS requires the IPv6 prefix configured on the global loopback interface to be a /128 prefix. _netlab_ automatically adjusts the **loopback.ipv6** prefix.
Expand Down
12 changes: 6 additions & 6 deletions docs/module/evpn.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ EVPN module supports IBGP- and EBGP-based EVPN:
| Cumulus 5.x (NVUE) | ✅ | ✅ | ✅ | ✅ |
| Dell OS 10 [❗](caveats-os10) | ✅ | ✅ | ✅ | ✅ |
| FRR | ✅ | ✅ | ✅ | ✅ |
| Nokia SR Linux | ✅ | ✅ | ❌ | ❌ |
| Nokia SR OS | ✅ | ✅ | ✅ | |
| Nokia SR Linux | ✅ | ✅ | ✅ | ✅ |
| Nokia SR OS | ✅ | ✅ | ✅ | |
| vJunos-switch | ✅ | ✅ | ❌ | ❌ |
| VyOS | ✅ | ✅ | ❌ | |
| VyOS | ✅ | ✅ | ❌ | |

With additional nerd knobs ([more details](evpn-weird-designs)), it's possible to implement the more convoluted designs, including:

Expand All @@ -76,14 +76,14 @@ With additional nerd knobs ([more details](evpn-weird-designs)), it's possible t
| Operating system | IBGP over<br>EBGP | EBGP<br>over EBGP |
| ------------------ | :-: | :-: |
| Arista EOS | ✅ | ✅ |
| Aruba AOS-CX | ✅ | |
| Aruba AOS-CX | ✅ | |
| Cisco Nexus OS | ❌ | ❌ |
| Cumulus Linux 4.x | ✅ | ✅ |
| Cumulus 5.x (NVUE) | ✅ | ✅ |
| Dell OS 10 | ✅ | ❌ |
| FRR | ✅ | ✅ |
| Nokia SR Linux | ✅ | |
| Nokia SR OS | ✅ | |
| Nokia SR Linux | ✅ | |
| Nokia SR OS | ✅ | |
| vJunos-switch | ✅ | ✅ |
| VyOS | ✅ | ❌ |

Expand Down
102 changes: 76 additions & 26 deletions netsim/ansible/templates/evpn/sros.j2
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
updates:
{# Configure EVPN AF on BGP neighbors #}
- path: configure/router[router-name=Base]
val:
bgp:
Expand Down Expand Up @@ -51,19 +52,10 @@ updates:
advertise: True # Symmetric IRB using RT5 prefixes
mac-ip:
advertise: False
{% endif %}
vxlan:
- vxlan-instance: 1
bgp-instance: 1
admin-state: enable
ecmp: {{ 1 if 'ixr' in clab.type else 8 }}
{% if is_routed %}
routed-vpls:
vxlan-ipv4-tep-ecmp: True # Enable ECMP for routed VXLAN
{% endif %}
{% endmacro %}

{% macro evpn_vprn %}
{% macro evpn_vprn() %}
{# Add it to the VPRN, enable evpn-tunnel and configure RT #}
- path: configure/service/vprn[service-name={{ vname }}]
val:
Expand All @@ -84,30 +76,88 @@ updates:
ecmp: {{ 1 if 'ixr' in clab.type else 8 }}
{% endmacro %}

{# Configure EVPN parameters for VLANs, TODO bundles #}
{# Configure EVPN parameters for simple MAC-VRF (VLAN) services #}
{% if vlans is defined %}
{% for vname,vdata in vlans.items() if vdata.evpn.evi is defined %}
- path: configure/service/vpls[service-name=vlan{{ vdata.id }}]
val:
bgp:
- bgp-instance: 1
# route-distinguisher: "{{ vdata.evpn.rd }}" # use auto-rd
route-target:
export: "target:{{ vdata.evpn.export[0] }}"
import: "target:{{ vdata.evpn.import[0] }}"
{% if vdata.mode|default('irb') == 'irb' %}
routed-vpls:
vxlan-ipv4-tep-ecmp: True # Enable ECMP for routed VXLAN
{% endif %}
bgp:
- bgp-instance: 1
route-distinguisher: "{{ vdata.evpn.rd }}"
route-target:
export: "target:{{ vdata.evpn.export[0] }}"
import: "target:{{ vdata.evpn.import[0] }}"
bgp-evpn:
evi: {{ vdata.evpn.evi }}
routes:
mac-ip:
advertise: True
{% if evpn.transport|default('vxlan') == 'mpls' %}
# TODO if evpn.transport == 'mpls'
mpls:
- bgp-instance: 1
admin-state: enable
ecmp: {{ 2 if 'ixr' in clab.type else 32 }}
# ingress-replication-bum-label: True # TODO, requires reserved label range
auto-bind-tunnel:
resolution: any
ecmp: {{ 2 if 'ixr' in clab.type else 32 }}
{% else %}
vxlan:
- vxlan-instance: 1
bgp-instance: 1
admin-state: enable
ecmp: {{ 1 if 'ixr' in clab.type else 8 }}
{% endif %}
{% endfor %}
{% endif %}

{# Configure EVPN parameters for IP-VRF services #}
{% if vrfs is defined %}
{% for vname,vdata in vrfs.items() if vdata.evpn.transit_vni is defined %}
- path: configure/service/vprn[service-name={{ vname }}]
val:
bgp-evpn:
{% if evpn.transport|default('vxlan') == 'mpls' %}
bgp-evpn:
evi: {{ vdata.evpn.evi }}
# TODO if evpn.transport == 'mpls'
mpls:
- bgp-instance: 1
admin-state: enable
ecmp: {{ 2 if 'ixr' in clab.type else 32 }}
mpls:
- bgp-instance: 1
admin-state: enable
ecmp: {{ 2 if 'ixr' in clab.type else 32 }}
# ingress-replication-bum-label: True # TODO, requires reserved label range
auto-bind-tunnel:
resolution: any
ecmp: {{ 2 if 'ixr' in clab.type else 32 }}
auto-bind-tunnel:
resolution: any
ecmp: {{ 2 if 'ixr' in clab.type else 32 }}
{% else %}
vxlan:
- vxlan-instance: 1
bgp-instance: 1
admin-state: enable
route-distinguisher: "{{ vdata.rd }}"
vrf-target:
export-community: "target:{{ vdata.export[0] }}"
import-community: "target:{{ vdata.import[0] }}"

vxlan:
instance:
- vxlan-instance: 1
vni: {{ vdata.evpn.transit_vni }}
{% endif %}
{% for proto in ['bgp','ospf','isis','ripv2'] if proto in vdata %}
#
- path: configure/policy-options/policy-statement[name={{ proto }}_{{ vname }}_export]
val:
entry:
- entry-id: 2000
from:
protocol:
name: [ evpn-ifl ]
action:
action-type: accept
{% endfor %}
{% endfor %}
{% endif %}
26 changes: 15 additions & 11 deletions netsim/devices/sros.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,21 @@ def vrf_route_leaking(node: Box) -> None:
node=node,
category=log.IncorrectValue)

def evpn_vrf_rp(node: Box) -> None:
for vname,vdata in node.get('vrfs',{}).items():
if not vdata.get('evpn',None):
"""
It looks like SR-OS does not apply AS-path loop detection parameters on EVPN AF
"""
def evpn_allowas_in(node: Box) -> None:
for ngb in node.get('bgp.neighbors',[]):
if not ngb.get('evpn',None):
continue
if vdata.get('bgp.neighbors',[]) or vdata.get('ospf'):
report_quirk(
text=f'We did not implement propagation of EVPN ip-prefix routes into VRF routing protocols',
more_data = f'Node {node.name} vrf {vname}',
quirk='evpn_rp',
node=node,
category=log.IncorrectValue)
if not ngb.get('allowas_in',None):
continue
report_quirk(
text=f'node {node.name}: cannot use "allowas_in" on BGP neighbor {node.name} with EVPN address family',
more_hints = f'It looks SR/OS does not apply AS-path loop detection parameters to EVPN AF',
quirk='evpn_allowas_in',
node=node,
category=log.IncorrectValue)

def set_port_mode(intf: Box, mode: str) -> None:
if '_port_mode' not in intf:
Expand Down Expand Up @@ -105,7 +109,7 @@ def device_quirks(self, node: Box, topology: Box) -> None:
ipv4_unnumbered(node)
vrf_route_leaking(node)
vxlan_vtep(node)
evpn_vrf_rp(node)
evpn_allowas_in(node)

def check_config_sw(self, node: Box, topology: Box) -> None:
need_ansible_collection(node,'nokia.grpc',version='1.0.2')