Skip to content

Commit da1f11d

Browse files
authored
SR-OS: Implement EVPN transit VNI within the VPRN (VRF) service (#2358)
Previous implementation created an extra VPLS service for the transit VNI, resulting in EVPN-IFF routes that could not be (easily) exported into other routing protocols. The VPRN EVPN instance results in EVPN-IFL routes which are easily matched in export routing policies.
1 parent f33fe52 commit da1f11d

File tree

4 files changed

+98
-45
lines changed

4 files changed

+98
-45
lines changed

docs/caveats.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -443,8 +443,7 @@ sudo pip3 install --upgrade 'ansible>=9.5.1'
443443

444444
Other caveats:
445445

446-
* In our current implementation, Nokia SR-OS does not propagate EVPN type-5 (IP prefix) routes into VRF routing protocols.
447-
* We did not implement inter-VRF route leaking. Every VRF is limited to one import and export route target (and they have to match).
446+
* We implemented inter-VRF route leaking only for MPLS/VPN deployments.
448447
* The SR OS configuration templates do not support additional routing policies on routing protocol route imports
449448
* An SR OS interface cannot use an unnumbered IPv4 address in combination with IPv6 GUA
450449
* SR OS requires the IPv6 prefix configured on the global loopback interface to be a /128 prefix. _netlab_ automatically adjusts the **loopback.ipv6** prefix.

docs/module/evpn.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ EVPN module supports IBGP- and EBGP-based EVPN:
6363
| Cumulus 5.x (NVUE) |||||
6464
| Dell OS 10 [](caveats-os10) |||||
6565
| FRR |||||
66-
| Nokia SR Linux ||| | |
67-
| Nokia SR OS |||| |
66+
| Nokia SR Linux ||| | |
67+
| Nokia SR OS |||| |
6868
| vJunos-switch |||||
69-
| VyOS |||| |
69+
| VyOS |||| |
7070

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

@@ -76,14 +76,14 @@ With additional nerd knobs ([more details](evpn-weird-designs)), it's possible t
7676
| Operating system | IBGP over<br>EBGP | EBGP<br>over EBGP |
7777
| ------------------ | :-: | :-: |
7878
| Arista EOS |||
79-
| Aruba AOS-CX || |
79+
| Aruba AOS-CX || |
8080
| Cisco Nexus OS |||
8181
| Cumulus Linux 4.x |||
8282
| Cumulus 5.x (NVUE) |||
8383
| Dell OS 10 |||
8484
| FRR |||
85-
| Nokia SR Linux || |
86-
| Nokia SR OS || |
85+
| Nokia SR Linux || |
86+
| Nokia SR OS || |
8787
| vJunos-switch |||
8888
| VyOS |||
8989

netsim/ansible/templates/evpn/sros.j2

Lines changed: 76 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
updates:
2+
{# Configure EVPN AF on BGP neighbors #}
23
- path: configure/router[router-name=Base]
34
val:
45
bgp:
@@ -51,19 +52,10 @@ updates:
5152
advertise: True # Symmetric IRB using RT5 prefixes
5253
mac-ip:
5354
advertise: False
54-
{% endif %}
55-
vxlan:
56-
- vxlan-instance: 1
57-
bgp-instance: 1
58-
admin-state: enable
59-
ecmp: {{ 1 if 'ixr' in clab.type else 8 }}
60-
{% if is_routed %}
61-
routed-vpls:
62-
vxlan-ipv4-tep-ecmp: True # Enable ECMP for routed VXLAN
6355
{% endif %}
6456
{% endmacro %}
6557

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

87-
{# Configure EVPN parameters for VLANs, TODO bundles #}
79+
{# Configure EVPN parameters for simple MAC-VRF (VLAN) services #}
8880
{% if vlans is defined %}
8981
{% for vname,vdata in vlans.items() if vdata.evpn.evi is defined %}
9082
- path: configure/service/vpls[service-name=vlan{{ vdata.id }}]
9183
val:
92-
bgp:
93-
- bgp-instance: 1
94-
# route-distinguisher: "{{ vdata.evpn.rd }}" # use auto-rd
95-
route-target:
96-
export: "target:{{ vdata.evpn.export[0] }}"
97-
import: "target:{{ vdata.evpn.import[0] }}"
84+
{% if vdata.mode|default('irb') == 'irb' %}
85+
routed-vpls:
86+
vxlan-ipv4-tep-ecmp: True # Enable ECMP for routed VXLAN
87+
{% endif %}
88+
bgp:
89+
- bgp-instance: 1
90+
route-distinguisher: "{{ vdata.evpn.rd }}"
91+
route-target:
92+
export: "target:{{ vdata.evpn.export[0] }}"
93+
import: "target:{{ vdata.evpn.import[0] }}"
94+
bgp-evpn:
95+
evi: {{ vdata.evpn.evi }}
96+
routes:
97+
mac-ip:
98+
advertise: True
99+
{% if evpn.transport|default('vxlan') == 'mpls' %}
100+
# TODO if evpn.transport == 'mpls'
101+
mpls:
102+
- bgp-instance: 1
103+
admin-state: enable
104+
ecmp: {{ 2 if 'ixr' in clab.type else 32 }}
105+
# ingress-replication-bum-label: True # TODO, requires reserved label range
106+
auto-bind-tunnel:
107+
resolution: any
108+
ecmp: {{ 2 if 'ixr' in clab.type else 32 }}
109+
{% else %}
110+
vxlan:
111+
- vxlan-instance: 1
112+
bgp-instance: 1
113+
admin-state: enable
114+
ecmp: {{ 1 if 'ixr' in clab.type else 8 }}
115+
{% endif %}
116+
{% endfor %}
117+
{% endif %}
98118

119+
{# Configure EVPN parameters for IP-VRF services #}
120+
{% if vrfs is defined %}
121+
{% for vname,vdata in vrfs.items() if vdata.evpn.transit_vni is defined %}
122+
- path: configure/service/vprn[service-name={{ vname }}]
123+
val:
124+
bgp-evpn:
99125
{% if evpn.transport|default('vxlan') == 'mpls' %}
100-
bgp-evpn:
101-
evi: {{ vdata.evpn.evi }}
102126
# TODO if evpn.transport == 'mpls'
103-
mpls:
104-
- bgp-instance: 1
105-
admin-state: enable
106-
ecmp: {{ 2 if 'ixr' in clab.type else 32 }}
127+
mpls:
128+
- bgp-instance: 1
129+
admin-state: enable
130+
ecmp: {{ 2 if 'ixr' in clab.type else 32 }}
107131
# ingress-replication-bum-label: True # TODO, requires reserved label range
108-
auto-bind-tunnel:
109-
resolution: any
110-
ecmp: {{ 2 if 'ixr' in clab.type else 32 }}
132+
auto-bind-tunnel:
133+
resolution: any
134+
ecmp: {{ 2 if 'ixr' in clab.type else 32 }}
135+
{% else %}
136+
vxlan:
137+
- vxlan-instance: 1
138+
bgp-instance: 1
139+
admin-state: enable
140+
route-distinguisher: "{{ vdata.rd }}"
141+
vrf-target:
142+
export-community: "target:{{ vdata.export[0] }}"
143+
import-community: "target:{{ vdata.import[0] }}"
144+
145+
vxlan:
146+
instance:
147+
- vxlan-instance: 1
148+
vni: {{ vdata.evpn.transit_vni }}
111149
{% endif %}
150+
{% for proto in ['bgp','ospf','isis','ripv2'] if proto in vdata %}
151+
#
152+
- path: configure/policy-options/policy-statement[name={{ proto }}_{{ vname }}_export]
153+
val:
154+
entry:
155+
- entry-id: 2000
156+
from:
157+
protocol:
158+
name: [ evpn-ifl ]
159+
action:
160+
action-type: accept
161+
{% endfor %}
112162
{% endfor %}
113163
{% endif %}

netsim/devices/sros.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,21 @@ def vrf_route_leaking(node: Box) -> None:
2828
node=node,
2929
category=log.IncorrectValue)
3030

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

4347
def set_port_mode(intf: Box, mode: str) -> None:
4448
if '_port_mode' not in intf:
@@ -105,7 +109,7 @@ def device_quirks(self, node: Box, topology: Box) -> None:
105109
ipv4_unnumbered(node)
106110
vrf_route_leaking(node)
107111
vxlan_vtep(node)
108-
evpn_vrf_rp(node)
112+
evpn_allowas_in(node)
109113

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

0 commit comments

Comments
 (0)