Skip to content

Commit 2ab7434

Browse files
ssassoStefano Sasso
andauthored
vJunos-switch: VXLAN and EVPN (#1993)
--------- Co-authored-by: Stefano Sasso <[email protected]>
1 parent e5a547c commit 2ab7434

File tree

7 files changed

+215
-1
lines changed

7 files changed

+215
-1
lines changed

docs/caveats.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,10 @@ See also [](caveats-junos).
336336

337337
* You can run Juniper vJunos-switch as a container packaged by Roman Dodin's fork of [vrnetlab](https://github.com/hellt/vrnetlab/). See [_containerlab_ documentation](https://containerlab.dev/manual/kinds/vr-vjunosswitch/) for further details.
338338
* Use a recent *vrnetlab* release that places the management interface into the **mgmt_junos** routing instance to avoid the conflict between [management IP subnet](clab-vrnetlab) `10.0.0.0/24` and **netlab** loopback addressing.
339+
* vJunos-switch VLAN configuration uses the so-called *Enterprise Style VLAN configuration* (which uses `family ethernet-switching` on unit 0 of interfaces).
340+
* For the above reason, the current netlab implementation of vJunos-switch EVPN configuration uses the `switch-options` (*default-switch*) configuration stanza, which leads to some drawbacks/limitations:
341+
* All EVPN routes are announced with the same RD (configured under `switch-options`). A RT is configured as well under `switch-options`, but then it is overwritten per-VNI under the `protocol evpn` configuration.
342+
* It is not possible to use multiple import/export RT. The *first* import RT is used on the configuration templates as the VNI RT.
339343

340344
See also [](caveats-junos).
341345

docs/module/evpn.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ The following table describes per-platform support of individual EVPN/VXLAN feat
3232
| FRR |||||
3333
| Nokia SR Linux |||||
3434
| Nokia SR OS |||||
35+
| vJunos-switch [](caveats-vjunos-switch) |||||
3536
| VyOS |||||
3637

3738
The following table describes per-platform support of individual EVPN/MPLS features:
@@ -64,6 +65,7 @@ EVPN module supports IBGP- and EBGP-based EVPN:
6465
| FRR |||||
6566
| Nokia SR Linux |||||
6667
| Nokia SR OS |||||
68+
| vJunos-switch |||||
6769
| VyOS |||||
6870

6971
With additional nerd knobs ([more details](evpn-weird-designs)), it's possible to implement the more convoluted designs, including:
@@ -82,6 +84,7 @@ With additional nerd knobs ([more details](evpn-weird-designs)), it's possible t
8284
| FRR |||
8385
| Nokia SR Linux |||
8486
| Nokia SR OS |||
87+
| vJunos-switch |||
8588
| VyOS |||
8689

8790
Most EVPN/VXLAN implementations support only IPv4 VXLAN transport; some can run VXLAN-over-IPv6:
@@ -97,6 +100,7 @@ Most EVPN/VXLAN implementations support only IPv4 VXLAN transport; some can run
97100
| FRR |||
98101
| Nokia SR Linux |||
99102
| Nokia SR OS |||
103+
| vJunos-switch |||
100104
| VyOS ||[](caveats-vyos) |
101105

102106
(evpn-global-parameters)=

docs/module/vxlan.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ The following table describes per-platform support of individual VXLAN features:
3535
| FRR ||||
3636
| Nokia SR Linux |[](caveats-srlinux) |||
3737
| Nokia SR OS ||||
38+
| vJunos-switch ||||
3839
| VyOS ||||
3940

4041
```{tip}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
{# EVPN config using mac-vrf & co #}
2+
3+
{# Enable BGP EVPN for specific neighbors #}
4+
protocols {
5+
bgp {
6+
{% for af in ['ipv4','ipv6'] if bgp[af] is defined and loopback[af] is defined %}
7+
group ibgp-peers-{{ af }} {
8+
{% for n in bgp.neighbors if n[af] is defined and n.type == 'ibgp' and n.evpn|default(false) %}
9+
neighbor {{ n[af] }} {
10+
family evpn {
11+
signaling;
12+
}
13+
}
14+
{% endfor %}
15+
}
16+
{% endfor %}
17+
group ebgp-peers {
18+
{% for n in bgp.neighbors if n.type == 'ebgp' and n.evpn|default(false) %}
19+
{% for af in ['ipv4','ipv6'] if n[af] is defined %}
20+
neighbor {{ n[af] }} {
21+
accept-remote-nexthop;
22+
family evpn {
23+
signaling;
24+
}
25+
}
26+
{% endfor %}
27+
{% endfor %}
28+
}
29+
}
30+
}
31+
32+
{# VERY DIRTY HACK here for initial testing - since we can specify only one vrf-target per vni-option, let's use the first import one #}
33+
{# - do it only if vxlan is defined - no need if we are RR only #}
34+
{% if vxlan is defined %}
35+
protocols {
36+
evpn {
37+
encapsulation vxlan;
38+
default-gateway no-gateway-community;
39+
extended-vni-list all;
40+
{% if vxlan.vlans is defined %}
41+
vni-options {
42+
{% for vname in vxlan.vlans if vlans[vname].vni is defined %}
43+
{% set vlan = vlans[vname] %}
44+
vni {{ vlan.vni }} {
45+
vrf-target target:{{ vlan.evpn.import[0] }};
46+
}
47+
{% endfor %}
48+
}
49+
{% endif %}
50+
}
51+
}
52+
{% endif %}
53+
54+
55+
{# define L3VNI on vrf routing-instance #}
56+
{% if vrfs is defined %}
57+
routing-instances {
58+
59+
{% for n,v in vrfs.items() if v.af is defined and v.evpn is defined %}
60+
{{ n }} {
61+
protocols {
62+
evpn {
63+
irb-symmetric-routing {
64+
vni {{ v.evpn.transit_vni }};
65+
}
66+
ip-prefix-routes {
67+
advertise direct-nexthop;
68+
encapsulation vxlan;
69+
vni {{ v.evpn.transit_vni }};
70+
export vrf-{{n}}-ebgp-export;
71+
}
72+
}
73+
}
74+
route-distinguisher {{ v.evpn.rd }};
75+
}
76+
{% endfor %}
77+
78+
}
79+
80+
{# update ospf, ibgp and ebgp export policy options for VRFs #}
81+
policy-options {
82+
{% for n,v in vrfs.items() if v.af is defined and v.evpn is defined %}
83+
policy-statement vrf-{{n}}-ospf-export {
84+
term redis_evpn {
85+
from protocol evpn;
86+
then accept;
87+
}
88+
}
89+
policy-statement vrf-{{n}}-ibgp-export {
90+
term redis_evpn {
91+
from protocol evpn;
92+
then accept;
93+
}
94+
}
95+
policy-statement vrf-{{n}}-ebgp-export {
96+
term redis_evpn {
97+
from protocol evpn;
98+
then accept;
99+
}
100+
term redis_bgp {
101+
from protocol bgp;
102+
then accept;
103+
}
104+
}
105+
{% endfor %}
106+
}
107+
108+
{# according to JunOS doc, in case NO ANYCAST GATEWAY is configured, enable 'proxy-macip-advertisement' on central IRB interfaces #}
109+
interfaces {
110+
{% for vname in vxlan.vlans|default([]) if vlans[vname].vni is defined and vlans[vname].mode|default('') == 'irb' and vlans[vname].vrf is defined %}
111+
{% set vlan = vlans[vname] %}
112+
{% if not vlan.gateway|default(false) %}
113+
irb.{{ vlan.id }} {
114+
proxy-macip-advertisement;
115+
}
116+
{% endif %}
117+
{% endfor %}
118+
}
119+
120+
{% endif %}

netsim/ansible/templates/vlan/vjunos-switch.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
{# for any vlan != route, define it #}
33
vlans {
4-
{% for vlan,vdata in vlans.items() if vdata.mode != 'route' %}
4+
{% for vlan,vdata in (vlans|default({})).items() if vdata.mode != 'route' %}
55
{{ vlan }} {
66
vlan-id {{ vdata.id }};
77

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
{#
2+
vJunos Switch VXLAN: different configuration required if VXLAN static flooding or EVPN-based
3+
#}
4+
5+
{# first of all, in any case, better to explicitly ECMP load balance per-flow #}
6+
policy-options {
7+
policy-statement ecmp {
8+
then {
9+
load-balance per-flow;
10+
}
11+
}
12+
}
13+
routing-options {
14+
forwarding-table {
15+
export ecmp;
16+
}
17+
}
18+
19+
{# define basic VXLAN config in switch-options stanza #}
20+
switch-options {
21+
vtep-source-interface {{ vxlan.vtep_interface }};
22+
}
23+
24+
{# define basic VLAN to VXLAN mapping #}
25+
{% if vxlan.vlans is defined %}
26+
vlans {
27+
{% for vname in vxlan.vlans if vlans[vname].vni is defined %}
28+
{% set vlan = vlans[vname] %}
29+
{{ vname }} {
30+
vxlan {
31+
vni {{ vlan.vni }};
32+
}
33+
}
34+
{% endfor %}
35+
}
36+
{% endif %}
37+
38+
{# different options for vxlan flooding types (static vs evpn) #}
39+
40+
{% if vxlan.flooding|default('') == 'static' %}
41+
42+
switch-options {
43+
{# need to list all possible static vtep here - fine tuning will be done per-vlan #}
44+
{% for remote_vtep in vxlan.vtep_list %}
45+
remote-vtep-list {{ remote_vtep }};
46+
{% endfor %}
47+
}
48+
49+
{# define static remote vteps for VXLANs #}
50+
{% if vxlan.vlans is defined %}
51+
vlans {
52+
{% for vname in vxlan.vlans if vlans[vname].vni is defined %}
53+
{% set vlan = vlans[vname] %}
54+
{{ vname }} {
55+
vxlan {
56+
ingress-node-replication;
57+
{% if vlan.vtep_list is defined %}
58+
{% for vtep in vlan.vtep_list %}
59+
static-remote-vtep-list {{ vtep }};
60+
{% endfor %}
61+
{% endif %}
62+
}
63+
}
64+
{% endfor %}
65+
}
66+
{% endif %}
67+
68+
{% endif %}
69+
70+
{% if vxlan.flooding|default('') == 'evpn' %}
71+
72+
{# use switch-options with "fake" RD and RT - the RT will be overwritten per-vni on the protocols->evpn #}
73+
switch-options {
74+
route-distinguisher {{ vxlan.vtep }}:65535;
75+
vrf-target target:{{ bgp.as|default(65535) }}:65535;
76+
}
77+
78+
{# need to define this to avoid validation errors #}
79+
protocols evpn encapsulation vxlan;
80+
81+
{% endif %}

netsim/devices/vjunos-switch.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,15 @@ group_vars:
66
netlab_device_type: vjunos-switch
77

88
features:
9+
evpn:
10+
asymmetrical_irb: true
11+
irb: true
912
vlan:
1013
model: l3-switch
1114
svi_interface_name: irb.{vlan}
1215
subif_name: "{ifname}.{vlan.access_id}"
1316
native_routed: true
17+
vxlan: true
1418

1519
clab:
1620
image: vrnetlab/juniper_vjunos-switch:23.4R2-S2.1

0 commit comments

Comments
 (0)