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
4 changes: 4 additions & 0 deletions docs/caveats.md
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,10 @@ See also [](caveats-junos).

* 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.
* 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.
* vJunos-switch VLAN configuration uses the so-called *Enterprise Style VLAN configuration* (which uses `family ethernet-switching` on unit 0 of interfaces).
* 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:
* 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.
* It is not possible to use multiple import/export RT. The *first* import RT is used on the configuration templates as the VNI RT.

See also [](caveats-junos).

Expand Down
4 changes: 4 additions & 0 deletions docs/module/evpn.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ The following table describes per-platform support of individual EVPN/VXLAN feat
| FRR | ✅ | ❌ | ✅ | ✅ |
| Nokia SR Linux | ✅ | ✅ | ✅ | ✅ |
| Nokia SR OS | ✅ | ❌ | ✅ | ✅ |
| vJunos-switch [❗](caveats-vjunos-switch) | ✅ | ❌ | ✅ | ✅ |
| VyOS | ✅ | ❌ | ✅ | ✅ |

The following table describes per-platform support of individual EVPN/MPLS features:
Expand Down Expand Up @@ -64,6 +65,7 @@ EVPN module supports IBGP- and EBGP-based EVPN:
| FRR | ✅ | ✅ | ✅ | ✅ |
| Nokia SR Linux | ✅ | ✅ | ❌ | ❌ |
| Nokia SR OS | ✅ | ✅ | ✅ | ✅ |
| vJunos-switch | ✅ | ✅ | ❌ | ❌ |
| VyOS | ✅ | ✅ | ❌ | ❌ |

With additional nerd knobs ([more details](evpn-weird-designs)), it's possible to implement the more convoluted designs, including:
Expand All @@ -82,6 +84,7 @@ With additional nerd knobs ([more details](evpn-weird-designs)), it's possible t
| FRR | ✅ | ✅ |
| Nokia SR Linux | ✅ | ❌ |
| Nokia SR OS | ✅ | ❌ |
| vJunos-switch | ✅ | ❌ |
| VyOS | ✅ | ❌ |

Most EVPN/VXLAN implementations support only IPv4 VXLAN transport; some can run VXLAN-over-IPv6:
Expand All @@ -97,6 +100,7 @@ Most EVPN/VXLAN implementations support only IPv4 VXLAN transport; some can run
| FRR | ✅ | ✅ |
| Nokia SR Linux | ✅ | ❌ |
| Nokia SR OS | ✅ | ❌ |
| vJunos-switch | ✅ | ❌ |
| VyOS | ✅ | ❌ [❗](caveats-vyos) |

(evpn-global-parameters)=
Expand Down
1 change: 1 addition & 0 deletions docs/module/vxlan.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ The following table describes per-platform support of individual VXLAN features:
| FRR | ✅ | ✅ | ✅ |
| Nokia SR Linux | ✅ [❗](caveats-srlinux) | ❌ | ❌ |
| Nokia SR OS | ✅ | ❌ | ❌ |
| vJunos-switch | ✅ | ✅ | ❌ |
| VyOS | ✅ | ✅ | ✅ |

```{tip}
Expand Down
120 changes: 120 additions & 0 deletions netsim/ansible/templates/evpn/vjunos-switch.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
{# EVPN config using mac-vrf & co #}

{# Enable BGP EVPN for specific neighbors #}
protocols {
bgp {
{% for af in ['ipv4','ipv6'] if bgp[af] is defined and loopback[af] is defined %}
group ibgp-peers-{{ af }} {
{% for n in bgp.neighbors if n[af] is defined and n.type == 'ibgp' and n.evpn|default(false) %}
neighbor {{ n[af] }} {
family evpn {
signaling;
}
}
{% endfor %}
}
{% endfor %}
group ebgp-peers {
{% for n in bgp.neighbors if n.type == 'ebgp' and n.evpn|default(false) %}
{% for af in ['ipv4','ipv6'] if n[af] is defined %}
neighbor {{ n[af] }} {
accept-remote-nexthop;
family evpn {
signaling;
}
}
{% endfor %}
{% endfor %}
}
}
}

{# 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 #}
{# - do it only if vxlan is defined - no need if we are RR only #}
{% if vxlan is defined %}
protocols {
evpn {
encapsulation vxlan;
default-gateway no-gateway-community;
extended-vni-list all;
{% if vxlan.vlans is defined %}
vni-options {
{% for vname in vxlan.vlans if vlans[vname].vni is defined %}
{% set vlan = vlans[vname] %}
vni {{ vlan.vni }} {
vrf-target target:{{ vlan.evpn.import[0] }};
}
{% endfor %}
}
{% endif %}
}
}
{% endif %}


{# define L3VNI on vrf routing-instance #}
{% if vrfs is defined %}
routing-instances {

{% for n,v in vrfs.items() if v.af is defined and v.evpn is defined %}
{{ n }} {
protocols {
evpn {
irb-symmetric-routing {
vni {{ v.evpn.transit_vni }};
}
ip-prefix-routes {
advertise direct-nexthop;
encapsulation vxlan;
vni {{ v.evpn.transit_vni }};
export vrf-{{n}}-ebgp-export;
}
}
}
route-distinguisher {{ v.evpn.rd }};
}
{% endfor %}

}

{# update ospf, ibgp and ebgp export policy options for VRFs #}
policy-options {
{% for n,v in vrfs.items() if v.af is defined and v.evpn is defined %}
policy-statement vrf-{{n}}-ospf-export {
term redis_evpn {
from protocol evpn;
then accept;
}
}
policy-statement vrf-{{n}}-ibgp-export {
term redis_evpn {
from protocol evpn;
then accept;
}
}
policy-statement vrf-{{n}}-ebgp-export {
term redis_evpn {
from protocol evpn;
then accept;
}
term redis_bgp {
from protocol bgp;
then accept;
}
}
{% endfor %}
}

{# according to JunOS doc, in case NO ANYCAST GATEWAY is configured, enable 'proxy-macip-advertisement' on central IRB interfaces #}
interfaces {
{% for vname in vxlan.vlans|default([]) if vlans[vname].vni is defined and vlans[vname].mode|default('') == 'irb' and vlans[vname].vrf is defined %}
{% set vlan = vlans[vname] %}
{% if not vlan.gateway|default(false) %}
irb.{{ vlan.id }} {
proxy-macip-advertisement;
}
{% endif %}
{% endfor %}
}

{% endif %}
2 changes: 1 addition & 1 deletion netsim/ansible/templates/vlan/vjunos-switch.j2
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

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

Expand Down
81 changes: 81 additions & 0 deletions netsim/ansible/templates/vxlan/vjunos-switch.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
{#
vJunos Switch VXLAN: different configuration required if VXLAN static flooding or EVPN-based
#}

{# first of all, in any case, better to explicitly ECMP load balance per-flow #}
policy-options {
policy-statement ecmp {
then {
load-balance per-flow;
}
}
}
routing-options {
forwarding-table {
export ecmp;
}
}

{# define basic VXLAN config in switch-options stanza #}
switch-options {
vtep-source-interface {{ vxlan.vtep_interface }};
}

{# define basic VLAN to VXLAN mapping #}
{% if vxlan.vlans is defined %}
vlans {
{% for vname in vxlan.vlans if vlans[vname].vni is defined %}
{% set vlan = vlans[vname] %}
{{ vname }} {
vxlan {
vni {{ vlan.vni }};
}
}
{% endfor %}
}
{% endif %}

{# different options for vxlan flooding types (static vs evpn) #}

{% if vxlan.flooding|default('') == 'static' %}

switch-options {
{# need to list all possible static vtep here - fine tuning will be done per-vlan #}
{% for remote_vtep in vxlan.vtep_list %}
remote-vtep-list {{ remote_vtep }};
{% endfor %}
}

{# define static remote vteps for VXLANs #}
{% if vxlan.vlans is defined %}
vlans {
{% for vname in vxlan.vlans if vlans[vname].vni is defined %}
{% set vlan = vlans[vname] %}
{{ vname }} {
vxlan {
ingress-node-replication;
{% if vlan.vtep_list is defined %}
{% for vtep in vlan.vtep_list %}
static-remote-vtep-list {{ vtep }};
{% endfor %}
{% endif %}
}
}
{% endfor %}
}
{% endif %}

{% endif %}

{% if vxlan.flooding|default('') == 'evpn' %}

{# use switch-options with "fake" RD and RT - the RT will be overwritten per-vni on the protocols->evpn #}
switch-options {
route-distinguisher {{ vxlan.vtep }}:65535;
vrf-target target:{{ bgp.as|default(65535) }}:65535;
}

{# need to define this to avoid validation errors #}
protocols evpn encapsulation vxlan;

{% endif %}
4 changes: 4 additions & 0 deletions netsim/devices/vjunos-switch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@ group_vars:
netlab_device_type: vjunos-switch

features:
evpn:
asymmetrical_irb: true
irb: true
vlan:
model: l3-switch
svi_interface_name: irb.{vlan}
subif_name: "{ifname}.{vlan.access_id}"
native_routed: true
vxlan: true

clab:
image: vrnetlab/juniper_vjunos-switch:23.4R2-S2.1
Expand Down