This is the third article in the ACX7k Metro Validation Series.
In this article, we validate the L2VPN feature scale support on the ACX7100-32C platform with 22.2R1 Junos-EVO image.
L2VPN is a BGP or LDP MPLS Enabled Solution to connect Customer Edge Devices (CEs) across a Provider Edge Network. RFC-6624 supports L2VPN using BGP for auto-discovery and Signalling. The PEs provide layer 2 bridged connectivity between CEs. The PEs of the network are connected via MPLS technology with the help of LDP, RSVP, SR-MPLS etc.
JUNOS-EVO supports L2VPN functionality with instance type "l2vpn". 8,000 L2VPN Instances were tested on ACX7100-32C. The same scale is tested on ACX7100-48L as well as on ACX7509 Scale is not covered in this article (same features but different scale are expected on this platform).
Please note that despite sharing the same ACX moniker, the ACX7000 products are different products than ACX500/710/1000/1100/2100/2200/4000/5000/5400/6000. They are powered by different Packet Forwarding Engines (PFE), and support different feature sets and scales.
Test topology consists of three routers, PE1, P1 and PE2, where ACX7100-32C is the PE1 and ACX7100-48L is the PE2 and P1 is that of PTX10008. PEs are connected to CEs using 4 x 100G links. CE's are simulated using a traffic generator. PEs are connected to the core using 8 x 100G links, which are bundled in 2 x LAGs each having four links.
The ACX7100-32C is the Device Under Test (DUT). The underlay transport used for testing is SR-MPLS with both OSPF and ISIS protocols individually. We also covered LDP as the underlay transport. The CE-bound interface configurations are of SP-Style (see glossary).
Test configures 8,000 L2VPN instances. Bidirectional traffic in iMIX mode at 99.9% offer-load flows for all the L2VPN services. A total of ~798 Gbps traffic flows through the DUT.
Each of the PE devices is connected to the traffic generator using 4 x 100G interfaces, each interface is logically split into 2000 VLANs to have 8000 interfaces, one interface bound to one L2VPN instance.
The first step to verify the L2VPN service is to make sure that the PE devices are having BGP established with l2vpn-signalling. As shown below from PE1, BGP is in Established state for Peer PE2(12.1.1.3).
regress@PE1> show l2vpn connections instance METRO_L2VPN_VRF_1
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 HS -- Hot-standby Connection
Legend for interface status
Up -- operational
Dn -- down
Instance: METRO_L2VPN_VRF_1
Edge protection: Not-Primary
Local site: s1 (1001)
connection-site Type St Time last up # Up trans
2001 rmt Up Oct 23 23:43:12 2022 1
Remote PE: 12.1.1.3, Negotiated control-word: No
Incoming label: 16, Outgoing label: 16
Local interface: et-0/0/0.1, Status: Up, Encapsulation: VLAN
Flow Label Transmit: No, Flow Label Receive: No
regress@PE1>
The following output captures the number of instances in the DUT
The Python Script is having three components, a Jinja File capturing the various configuration templates, a Params File capturing the various user variables and the script uses both these input files and generates the required configurations and commit that in the router.
Note: The configs are generated as per the CE-bound interface schema.
#! /usr/bin/python
"""
FileName: create_l2vpn_vrf.py
Version: 1.0
Description: This script will create l2vpn vrf instances and configure it on the router
Author: Suneesh Babu
"""
import yaml
from glob import glob
from jinja2 import Template
import ipaddress
from jnpr.junos.utils.config import Config
from jnpr.junos import Device
from jnpr.junos.factory import loadyaml
from jnpr.junos.op import *
def iflrange(ifd_name, start_unit, max):
"""
This subroutine yields the specified number of l3 ifls for the ifd
"""
while(max):
iflname = ifd_name + '.' + str(start_unit)
yield iflname
start_unit += 1
max -= 1
def router_operation(config_filename, data, mode):
"""
This sub-routine connectes to the router and do the necessary commit operations
"""
router = Device(host=data['host'], user=data['username'], password=data['password'], port=22)
router.open()
cfg = Config(router)
if mode == 'jinja':
cfg.load(template_path=config_filename, template_vars=data, format='text', merge=True)
elif mode == 'setfile':
cfg.load(path=config_filename, format='set')
cfg.pdiff()
cfg.commit()
router.close()
def jinja_template_input(data):
"""
This sub-routine yields the variables required for the jinja template
"""
ifl_unit_list = range(int(data['ifl_start_unit']), int(data['ifl_start_unit']) + int(data['vrf_max']))
vlan_list = range(int(data['vlan_id_start']), int(data['vlan_id_start']) + int(data['vrf_max']))
vrf_id_list = range(int(data['vrf_id']), int(data['vrf_id']) + int(data['vrf_max']))
ifl_name_list = iflrange(data['ifd_name'], data['ifl_start_unit'], int(data['vrf_max']))
return zip(ifl_unit_list, vlan_list), zip(vrf_id_list, list(ifl_name_list))
def main():
"""
To Build the desired number of l2vpn routing-instances
"""
print("Step-1: Read the Variables from the Params File")
with open(glob('l2vpn_params.yaml')[0]) as fh:
data = yaml.safe_load(fh.read())
print("Step-2: Build the Data Feed for the Jinja Template Input")
ifl_attributes, l2vpn_attributes = jinja_template_input(data)
data['ifl_variables'] = ifl_attributes
data['l2vpn_variables'] = l2vpn_attributes
print("Step-3: Build the configuration file from Jinja Template")
with open(glob('l2vpn_jinja.j2')[0]) as t_fh:
t_format = t_fh.read()
l2vpn_snippet = Template(t_format)
print (l2vpn_snippet.render(data))
print("Step-4: Load the config into router and commit it")
# router_operation('l2vpn_jinja.j2', data, 'jinja')
if __name__ == '__main__':
main()
ACX7000 (ACX7100-32C, ACX7100-48L, ACX7509) can scale to 8000 L2VPN instances and interfaces making it a perfectly suitable platform for Metro aggregation. Next article will be dedicated to VPLS validation, stay tuned :)