It has been a busy few weeks trying to stay ahead of all the new work that has been coming towards myself and the team, due to the in sourcing of the core network! Lucky enough for my team, we have finally got our hands onto full end-to-end connectivity! Fun times 😀
With that being said, I’ve been given a wee project to provision a circuit for a business customer between two sites for a Proof Of Concept. As this circuit is being using as a POC (for now), it was agreed that a Layer 2 VPN (L2VPN/pseudowire) will be best suited, because a simple point-to-point connection was needed between two PEs. As we have a MPLS enabled network, it was decided that would be the easiest way to get their POC up and running quickly, as we were under a bit of a hard deadline!
For me, it was good little project, even though I know what L2VPNs were and how they work, I had never configured one myself. You see where I’m going with this now?
This post will over note how to configure L2VPN with Junos 😀
L2VPN, also known as a pseudowire, is defined in RFC4665, where they are called Virtual Private Wire Service (VPWS):
In essence, L2VPNs are virtual point-to-point circuit that use the underlying Transport Labels (LDP/RSVP) or a statically defined MPLS path to go between two PE’s, that allows the extension of a layer 2 broadcast domain. If you need multiple sites on the same layer 2 broadcast you will need to consider Virtual Private Lan Service (VPLS) or Ethernet VPN (EVPN).
Within Junos there are 3 ways of configuring L2VPNs, two are regarded as modern way and has been rectified with RFC’s with an additional legacy method. Kompella and Martini are regarded as the industry standard, with Circuit Cross-Connect (CCC) seen as legacy:
- Circuit Cross-Connect: The Circuit Cross-Connect style of L2VPN uses a single Outer Label, also known as the Tunnel/Transport Label, to transport L2 payload from PE to PE. CCC can ONLY use RSVP as MPLS transport, in addition each CCC connection has its own dedicated RSVP-signalled LSP associated, the transport label cannot be shared between multiple connections. LSPs are manually created on each PE to determines which circuit the frame belongs to on the other end.
- Martini: The Martini style of L2VPN has a pair of labels before the L2 frame. The Outer label is the transport mechanism that allows the frame from egress interface from the sending PE to ingress interface of the receiving PE. The Inner label, known as the VC Label, is the label that informs the receiving PE, where the L2VPN payload should go. It is important to note that if you are using the Martini style, although either LDP or RVSP can be used MPLS transport, that LDP is used for the signalling of the VC label. So if the RSVP is used as the MPLS transport, LDP will need to be enabled on the loopback address of both PE routers. A minimum of 2 LSPs will need to be set, as MPLS LSPs are unidirectional.
- Kompella: The Kompella style of L2VPN is similar to Martini style as both use stacked labels before the Layer 2 payload and both can use LDP, RSVP or both as Transport Label. There difference comes in that unlike Martini, Kompella uses BGP signalling as its VC Label. This means you will need to have BGP enabled network, in addition, it’s not compulsory to send static LSPs as BGP provides a mechanism for autodiscovery of new point-to-point links similar to a VPLS. Although Kompella has a more complex configuration, because of its usage of BGP signalling it is regarded as the best option for large scale deployments as it will in-conjunction with other BGP families. RFC6624 has more details on L2VPN using BGP for Auto-Discovery and Signaling
In our network, we use the Kompella style of L2VPNs. The bulk and most depth of my testing was with that method… Although I was able to get a wee bit of naughty time after to configure the other methods 🙂
The topology I’ll be working with is a simple one. I’ve a got a single MX480 broken up into 3 Logical Systems.

The underlying IGP is IS-IS with RSVP, LDP and BGP enabled. This is a mirror, of what we have in production. With all the L2VPNs the customer facing physical interface has to be set to the correct encapsulation. For my testing, as I wont be using VLANs, Bridging or Setting a VPLS. I used ethernet-ccc and had set the logical interface to family ccc, you can find out more about the different physical encapsulations here
set interfaces xe-0/1/0 enable set interfaces xe-0/1/0 encapsulation ethernet-ccc set interfaces xe-0/1/0 unit 0 family ccc
set protocols rsvp interface xe-1/0/0.0 set protocols rsvp interface xe-1/0/2.0
set protocols mpls explicit-null set protocols mpls ipv6-tunneling set protocols mpls no-decrement-ttl set protocols mpls interface xe-1/0/0.0 set protocols mpls interface xe-1/0/2.0
set protocols bgp group Master type internal set protocols bgp group Master local-address 192.168.2.1 set protocols bgp group Master family inet unicast set protocols bgp group Master family inet6 unicast set protocols bgp group Master local-as 100 set protocols bgp group Master neighbor 192.168.2.2 set protocols bgp group Master neighbor 192.168.2.3
set protocols isis reference-bandwidth 1000g set protocols isis level 1 disable set protocols isis level 2 wide-metrics-only set protocols isis interface xe-1/0/0.0 ldp-synchronization set protocols isis interface xe-1/0/0.0 point-to-point set protocols isis interface xe-1/0/0.0 link-protection set protocols isis interface xe-1/0/2.0 ldp-synchronization set protocols isis interface xe-1/0/2.0 point-to-point set protocols isis interface xe-1/0/2.0 link-protection set protocols isis interface xe-1/0/3.0 ldp-synchronization set protocols isis interface xe-1/0/3.0 point-to-point set protocols isis interface xe-1/0/3.0 link-protection set protocols isis interface lo0.0
sset protocols ldp track-igp-metric set protocols ldp explicit-null set protocols ldp transport-address router-id set protocols ldp interface xe-1/0/0.0 set protocols ldp interface xe-1/0/2.0 set protocols ldp interface lo0.0
All configurations will be done on the Master and SiteA, and for my examples I will show work done on the Master Instance. With all that out of the way… Let’s get cracking 😀
Kompella
As stated before, BGP is used as the VPN signalling method, with that in mind, we will need to enable layer-2 signalling within MP-BGP. This is simply done by adding the command family l2vpn signaling with the BGP stanza. This can be added globally within BGP or under the specific neighbour.
set protocols bgp group Master family l2vpn signaling
With the signalling sorted we can go straight into the configuration of the L2VPN. Just like L3VPNs, L2VPNs configuration is done within the routing-instance stanza and uses the same parameters as L3VPN by having Route Distinguisher (RD) and Route-Target/vrf-target (RT). The RD has to be unique per device with RT matching on all devices within the L2VPN, this is important, so that traffic can be routed accordingly per site. In addition, routing-instance has to be set to l2vpn and the interface(s) have to be defined within the routing-instance as well.
set routing-instances Master instance-type l2vpn set routing-instances Master interface xe-0/1/0.0 set routing-instances Master route-distinguisher 100:0001 set routing-instances Master vrf-target target:100:0000
Next the properties for that site within the L2VPN will need to configured under protocol l2vpn within the routing-instance. The encapsulation has to match all site that want to participate within the VPN. The Site identifier must be unique to the entire site within the L2VPN as the site ID is used to compute label values for site-to-site communications. The interface(s) have to be defined within l2vpn and l2vpn site stanzas.
set routing-instances Master protocols l2vpn encapsulation-type ethernet set routing-instances Master protocols l2vpn interface xe-0/1/0.0 set routing-instances Master protocols l2vpn site Master site-identifier 1 set routing-instances Master protocols l2vpn site Master interface xe-0/1/0.0
Verification
The primary command that will be used to check the status of a pseudowire would be show l2vpn connections. As Komplella signalling uses BGP, we will be able to do a show bgp summary and see a route being advertised within the l2vpn and routing instance tables show route table Master.l2vpn.0 or show route table bgp.l2vpn.0 respectfully. Additionally we will be able to mpls.0 table to confirm that the L2VPN incoming label and interface(s) for the pseudowire have made the routing table, by using show route table mpls.0.
[email protected]> show l2vpn connections Layer-2 VPN connections: Legend for connection status (St) EI -- encapsulation invalid NC -- interface encapsulation not CCC/TCC/VPLS EM -- encapsulation mismatch WE -- interface and instance encaps not same VC-Dn -- Virtual circuit down NP -- interface hardware not present CM -- control-word mismatch -> -- only outbound connection is up CN -- circuit not provisioned <- -- only inbound connection is up OR -- out of range Up -- operational OL -- no outgoing label Dn -- down LD -- local site signaled down CF -- call admission control failure RD -- remote site signaled down SC -- local and remote site ID collision LN -- local site not designated LM -- local site ID not minimum designated RN -- remote site not designated RM -- remote site ID not minimum designated XX -- unknown connection status IL -- no incoming label MM -- MTU mismatch MI -- Mesh-Group ID not available BK -- Backup connection ST -- Standby connection PF -- Profile parse failure PB -- Profile busy RS -- remote site standby SN -- Static Neighbor LB -- Local site not best-site RB -- Remote site not best-site VM -- VLAN ID mismatch Legend for interface status Up -- operational Dn -- down Instance: Master Local site: Master (1) connection-site Type St Time last up # Up trans 2 rmt Up Jun 4 12:36:46 2016 2 Remote PE: 192.168.2.2, Negotiated control-word: Yes (Null) Incoming label: 800001, Outgoing label: 800000 Local interface: xe-0/1/0.0, Status: Up, Encapsulation: ETHERNET
[email protected]> show bgp summary Groups: 1 Peers: 2 Down peers: 0 Table Tot Paths Act Paths Suppressed History Damp State Pending inet.0 0 0 0 0 0 0 inet6.0 0 0 0 0 0 0 bgp.l2vpn.0 1 1 0 0 0 0 Peer AS InPkt OutPkt OutQ Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped... 192.168.2.2 100 3234 3229 0 1 1d 0:19:17 Establ inet.0: 0/0/0/0 inet6.0: 0/0/0/0 Master.l2vpn.0: 1/1/1/0 bgp.l2vpn.0: 1/1/1/0 192.168.2.3 100 5735 5724 0 1 1d 19:06:59 Establ inet.0: 0/0/0/0 inet6.0: 0/0/0/0 Master.l2vpn.0: 0/0/0/0 bgp.l2vpn.0: 0/0/0/0/
[email protected]> show route table Master.l2vpn.0 Master.l2vpn.0: 2 destinations, 2 routes (2 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 100:1:1:1/96 *[L2VPN/170/-101] 1d 20:37:12, metric2 1 Indirect 100:2:2:1/96 *[BGP/170] 00:01:02, localpref 100, from 192.168.2.2 AS path: I, validation-state: unverified > to 192.168.1.14 via xe-1/0/0.0, Push 0 to 192.168.1.6 via xe-1/0/2.0, Push 300000
[email protected]> show route table mpls.0 protocol l2vpn mpls.0: 10 destinations, 10 routes (10 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 800001 *[L2VPN/7] 23:30:09 > via xe-0/1/0.0, Pop Offset: 4 xe-0/1/0.0 *[L2VPN/7] 00:06:20, metric2 100 > to 192.168.1.14 via xe-1/0/0.0, Push 800000 Offset: 252 to 192.168.1.6 via xe-1/0/2.0, Push 800000, Push 300000(top) Offset: 252
From the end host point of view, we have end-to-end connectivity 😀
[email protected]:~$ ping -c 2 -q 192.168.137.3 PING 192.168.137.3 (192.168.137.3) 56(84) bytes of data. --- 192.168.137.3 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1000ms rtt min/avg/max/mdev = 0.431/0.637/0.843/0.206 ms
Martini
Martini signalling uses LDP, as stated before, and with LDP enabled already, I will focus on the actual configuration, which is done within the protocol l2circuit stanza. Compared to Kompella, the configuration for Martini style of L2VPNs is much simpler. All that is needed is for:
- The remote neighbour to be defined. In my example I will be using the loopback address SiteA as the remote neighbour
- The customer facing interface connecting into the VPN
- Set a circuit ID, that must match on both sides
All this can be done in one line!
set protocols l2circuit neighbor 192.168.2.2 interface xe-0/1/0.0 virtual-circuit-id 1
With that we have Martini style L2VPN configured 🙂
Verifications
To check the status of Martini style L2VPN, you will use show l2circuit connections, the output is near enough the same as show l2vpn connections. Martini, as discussed above, uses LDP for the signalling, we will be able to use show ldp neighbor to check that the neighbour relationship with the remote side has been successful and we will be able to check the LDP database by using show ldp database to verify that new labels associated with the pseudowire (L2CKT) has been installed into the database. Additionally you can check the inet.3 and mpls.0 routing tables, by using show route table inet.3 & show route table mpls.0
[email protected]> show l2circuit connections Layer-2 Circuit Connections: Legend for connection status (St) EI -- encapsulation invalid NP -- interface h/w not present MM -- mtu mismatch Dn -- down EM -- encapsulation mismatch VC-Dn -- Virtual circuit Down CM -- control-word mismatch Up -- operational VM -- vlan id mismatch CF -- Call admission control failure OL -- no outgoing label IB -- TDM incompatible bitrate NC -- intf encaps not CCC/TCC TM -- TDM misconfiguration BK -- Backup Connection ST -- Standby Connection CB -- rcvd cell-bundle size bad SP -- Static Pseudowire LD -- local site signaled down RS -- remote site standby RD -- remote site signaled down HS -- Hot-standby Connection XX -- unknown Legend for interface status Up -- operational Dn -- down Neighbor: 192.168.2.2 Interface Type St Time last up # Up trans xe-0/1/0.0(vc 1) rmt Up Jun 5 14:03:37 2016 1 Remote PE: 192.168.2.2, Negotiated control-word: Yes (Null) Incoming label: 300000, Outgoing label: 300016 Negotiated PW status TLV: No Local interface: xe-0/1/0.0, Status: Up, Encapsulation: ETHERNET Flow Label Transmit: No, Flow Label Receive: No
[email protected]> show ldp neighbor Address Interface Label space ID Hold time 192.168.2.2 lo0.0 192.168.2.2:0 43 192.168.1.6 xe-1/0/2.0 192.168.2.3:0 14 192.168.1.14 xe-1/0/0.0 192.168.2.2:0 13
[email protected]> show ldp database Input label database, 192.168.2.1:0--192.168.2.2:0 Label Prefix 299984 192.168.2.1/32 0 192.168.2.2/32 300000 192.168.2.3/32 300016 L2CKT CtrlWord ETHERNET VC 1 Output label database, 192.168.2.1:0--192.168.2.2:0 Label Prefix 0 192.168.2.1/32 299968 192.168.2.2/32 299984 192.168.2.3/32 300000 L2CKT CtrlWord ETHERNET VC 1 Input label database, 192.168.2.1:0--192.168.2.3:0 Label Prefix 300016 192.168.2.1/32 300000 192.168.2.2/32 0 192.168.2.3/32 Output label database, 192.168.2.1:0--192.168.2.3:0 Label Prefix 0 192.168.2.1/32 299968 192.168.2.2/32 299984 192.168.2.3/32
[email protected]> show route table inet.3 192.168.2.2 inet.3: 3 destinations, 4 routes (3 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 192.168.2.2/32 *[LDP/9] 1d 21:16:06, metric 100 > to 192.168.1.14 via xe-1/0/0.0, Push 0 to 192.168.1.6 via xe-1/0/2.0, Push 300000 [RSVP/10/1] 1d 01:14:11, metric 100 > to 192.168.1.6 via xe-1/0/2.0, label-switched-path to-siteA
[email protected]> show route table mpls.0 protocol l2circuit mpls.0: 10 destinations, 10 routes (10 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 300000 *[L2CKT/7] 00:05:13 > via xe-0/1/0.0, Pop Offset: 4 xe-0/1/0.0 *[L2CKT/7] 00:05:13, metric2 100 > to 192.168.1.14 via xe-1/0/0.0, Push 300016 Offset: 252 to 192.168.1.6 via xe-1/0/2.0, Push 300016, Push 300000(top) Offset: 252
From the end host point of view, connectivity between the two is there 🙂
[email protected]:~$ ping -c 2 -q 192.168.137.3 PING 192.168.137.3 (192.168.137.3) 56(84) bytes of data. --- 192.168.137.3 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 0.358/0.532/0.707/0.176 ms
Circuit Cross-Connect
As CCC doesn’t support stacked labels unlike Kompella and Martini, we will need to configure 2 static LSPs between the PE routers. CCC needs to have a LSP for to transmit and another to receive traffic. So firstly, we will need to get the LSPs configured. The received LSP will be configured on the remote PE, so under protocols mpls label-switched-path stanza, this is where we will define the LSP. I've used the loopback address of the remote end with the underlying IGP working out the best path.
set protocols mpls label-switched-path to-siteA to 192.168.2.2 set protocols mpls label-switched-path to-siteA no-cspf
With the LSPs configured, we will need to go under the protocol connections stanza. We need to define the customer facing interface(s) that will be connecting into the VPN, then set the transmit LSP and receive LSP, this will be the name of the LSP set on the remote end.
set protocols connections remote-interface-switch siteA interface xe-0/1/0.0 set protocols connections remote-interface-switch siteA transmit-lsp to-siteA set protocols connections remote-interface-switch siteA receive-lsp to-Master
With that we are sorted!
Verifications
In regards with CCC there's less show commands, from what I’ve found (let me know if there's more please), but we can check the pseudowire's status by using show connections. We can confirm the Transmit (Ingress) and Receive (Egress) LSP using show mpls lsp and finally, we will be able to mpls.0 table to confirm that the L2VPN incoming label and interface(s) for the pseudowire have made the routing table, by using show route table mpls.0.
[email protected]> show connections CCC and TCC connections [Link Monitoring On] Legend for status (St): Legend for connection types: UN -- uninitialized if-sw: interface switching NP -- not present rmt-if: remote interface switching WE -- wrong encapsulation lsp-sw: LSP switching DS -- disabled tx-p2mp-sw: transmit P2MP switching Dn -- down rx-p2mp-sw: receive P2MP switching -> -- only outbound conn is up Legend for circuit types: <- -- only inbound conn is up intf -- interface Up -- operational oif -- outgoing interface RmtDn -- remote CCC down tlsp -- transmit LSP Restart -- restarting rlsp -- receive LSP Connection/Circuit Type St Time last up # Up trans siteA rmt-if Up Jun 3 12:42:55 1 xe-0/1/0.0 intf Up to-siteA tlsp Up to-Master rlsp Up
[email protected]> show mpls lsp Ingress LSP: 1 sessions To From State Rt P ActivePath LSPname 192.168.2.2 192.168.2.1 Up 0 * to-siteA to-siteA Total 1 displayed, Up 1, Down 0 Egress LSP: 1 sessions To From State Rt Style Labelin Labelout LSPname 192.168.2.1 192.168.2.2 Up 0 1 FF 300080 - to-Master Total 1 displayed, Up 1, Down 0 Transit LSP: 0 sessions Total 0 displayed, Up 0, Down 0
[email protected]> show route table mpls.0 protocol ccc mpls.0: 10 destinations, 10 routes (10 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 300080 *[CCC/7] 00:00:04 > via xe-0/1/0.0, Pop xe-0/1/0.0 *[CCC/10/1] 00:00:04, metric 100 > to 192.168.1.14 via xe-1/0/0.0, label-switched-path to-siteA
Finally to confirm end-to-end reachability between the end hosts
[email protected]:~$ ping -c 2 -q 192.168.137.3 PING 192.168.137.3 (192.168.137.3) 56(84) bytes of data. --- 192.168.137.3 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 0.358/0.532/0.707/0.176 ms
I had planned to have a wee bit more to this post, with what I was actually testing ,however, this is getting a bit longer than I expected, so I'll make this into a two-part 😉
My next post will detail, how you can use traffic engineering to manipulate a L2VPN path between 2 PE routers! Hope to see you there 😀
References
Darren's Blog L2VPN in Junos
RFC4665
MPLS l2VPN
RFC6624
RFC6074
Vlan based CCC L2vpn