The posts I’ve done about JUNOS so far all have to do with a single theme: Reducing operational risk. The features I like about JUNOS are the features that help me avoid screwing up a configuration. As I’ve said in past posts and undoubtedly will say many times again, the biggest cause of network outages is not hardware or software failures, it’s folks making configuration changes.
As a general practice, insuring that every configuration on every router in your network follows a standard configuration policy will reduce errors. What that policy is can vary from one network to another, but a consistent and enforceable policy within the network means that everyone configuring a router knows the rules for creating the configuration. Everyone troubleshooting the network knows what information to expect to find in any configuration.
In the previous post I wrote about how you can create a custom script that runs checks on a JUNOS candidate configuration when the commit command is issued, and prevents the configuration from becoming active if the script finds something out of spec. It’s a great tool for insuring that every configuration is in compliance with the standards you define for your network.
Another potential source of variation and mistakes happens when a relatively long set of configuration statements must be created for a single function. Setting up a single MPLS VPN instance, for example, or a single BGP peer group, can involve quite a few statements. This is where JUNOS macros can help.
A macro is a script, but it does more than error checking. It can take relatively simple input and write a complete configuration for you.
Here’s an example I’ve used countless times. I want to create a VPLS instance named vpls-100. Although the configuration for the instance is complex, most of the statements are repeated consistently for every VPLS instance; there are only a few variables for this specific instance.
vpls-100 {When the configuration is committed, the macro uses those few specified variables along with many other variables that are standard to every VPLS instance, and thus specified in the macro itself, to create the full VPLS instance, the interface configuration, and the routing policy entry for the instance:routing-instances { If you look through the resulting configuration you’ll find the variables specified in the custom input syntax. You’ll also find quite a few statements that include variables that the macro put in on its own.
Rather than write the entire configuration manually, I call up a custom macro named vpls-inst, and specify the variables to be used for this instance: The VPN ID (100), the local interface on which the VPLS instance is to run (ge-0/0/0.10), the Site ID (2), and an export policy to apply (ASD-2A):
apply-macro vpls-inst {
id 100;
interface ge-0/0/0.10;
site 2;
via ASD-2A;
}
}
vpls-100 {
/* # Generated by vpls-inst.xsl # */
instance-type vpls;
interface ge-0/0/0.10;
route-distinguisher 192.168.0.92:100;
vrf-export [ CUST_VIA_ASD-2A CUST-vpls-100 ];
vrf-target import target:100:100;
protocols {
vpls {
site-range 24;
mac-table-size 2000;
site cressida {
site-identifier 2;
}
}
}
}
}
interfaces {
ge-0/0/0 {
unit 10 {
description vpls-100;
encapsulation vlan-vpls;
vlan-id 10;
input-vlan-map {
swap;
vlan-id 100;
}
output-vlan-map swap;
}
}
}
policy-options {
policy-statement CUST-vpls-100 {
then {
community add CUST-vpls-100;
accept;
}
}
community CUST-vpls-100 members target:100:100;
}
The macro itself is a bit too long to display in this post, and they’re not all that easy to write. But the point is that your top-tier engineers can write the macro – or a set of macros – once, and all operational people can then consistently use it. The result is consistent, error-free configurations that are completely in compliance with whatever rules you want to enforce for your configurations.