It is common in high availability environments to deploy two routers side by side, often in an active/passive pair, and to use something like VRRP to share a default gateway address between the two routers. So if the primary router goes away, the second router will take over the gateway address -- and the traffic -- once it notices the primary router is no longer there.

In many production environments where there is planned maintenance on the primary (active) router, the preference is to divert the traffic onto the secondary (passive) router in a staged manner, before starting the maintenance. And to return it to the primary router when the maintenance is complete. For VRRP this can be done by altering the VRRP priority on the secondary to be "more desirable" (high priority) than the VRRP priority on the primary, forcing a VRRP election and forcing the previously passive router to take over the gateway address and the traffic.

Unfortunately the detail is more complicated than "change the VRRP priority". Because (in most implementations) there is one VRRP neogtiation domain per VLAN (since VRRP communicates using multicast, and that multicast normally does not cross the broadcast domain -- the VLAN). Which means that for a given router there will be several VRRP configurations to change; in an ISP router there will be dozens or hundreds to change. A further complication is that the range of VRRP identifiers is different (1-255) than the range of VLAN identifiers (1-4095). Which means that the VRRP identifier may or may not be the same as the VLAN identifier -- depending on the VLAN identifiers used.

In JunOS (at least on J-series routers), the VRRP priority is buried well down the configuration hierachy under:

  • the physical interface
  • the logical ("unit") on that interface (usually the same as VLAN ID in practice)
  • the IPv4 family ("inet")
  • the IP in the shared subnet
  • the VRRP group number

which means that in order to change the VRRP priority one needs to know all of those details. The need to know ("interface/unit", "shared IP address", and "VRRP group number") tuples, for every combination on the router, in order to do a mass change greatly complicates doing a quick "just adjust the priorities of everything" swap over. (Some other platforms, eg, VRRP on Mikrotik make the VRRP priority much more accessible, through the creation of virtual interfaces at the top level -- which makes a mass change much easier. The JunOS configuration layout seems to have been designed for JunOS developer convenience when creating VRRP packets on the wire, rather than operational convenience.)

On JunOS, to do a mass change you want a series of commands like these:

set interfaces ge-0/0/3 unit XX family inet address A.B.C.D/M vrrp-group ZZ priority 200

in order to effect the change (assuming all your VRRP is on the same physical interface -- a common scenario in an ISP router configuration, as you will normally use a dynamic routing protocol like OSPF or BGP on the other interfaces). Here "XX" is the logical interface (unit) identifier (often also the VLAN identifer, but we do not need that as such), "A.B.C.D/M" is the shared IP address, and "ZZ" is the VRRP group number.

These values are spread out in the "interfaces" section of the configuration:

[...]
ge-0/0/3 {
    [....]
    unit XX {
        vlan-id XX;
        family inet {
            [...]
            address A.B.C.D/M {
                vrrp-group ZZ {
                    virtual-address A.B.C.E;
                    priority 100;
                }
            }
        }
    }
    [....]
}

But with some brute force scripting it is possible to pull the right values out of an existing configuration file, and generate a set of VRRP priority change commands. (In our example production configuration the primary has a VRRP priority of 150; the secondary normally has a VRRP priority of 100, but when it is desired to make it take over the traffic we set its VRRP priority to 200.)

For future reference, a magic shell script to do this is:

zcat juniper.conf.gz | 
     awk -v new_priority=100 'BEGIN { junos_set=""; }
           /unit/        {junos_set = "set interfaces ge-0/0/3 " $1 " " $2;}
           /address.*\// {junos_set = junos_set " family inet " $1 " " $2; }
           /vrrp-group/  {junos_set = junos_set " " $1 " " $2;             }
           /priority/    {print junos_set " priority " new_priority; 
                          junos_set="";}'

(This is a rewritten version of the initial hacky command line, in awk rather than perl -- mostly to avoid the conflicts between the perl NULL file handle operator, and HTML entities. But it also makes the script more readable. And allows a command line variable to change the desired priority.)

With that script it is the work of a minute to download the existing config, generate lines to change the VRRP priority of all interfaces, paste them in, apply them in a batch, and then carry on with the maintenance on the primary. And then generate a new set of VRRP priority changes to revert to the primary carrying the active traffic. So hopefully you too can have relatively transparent maintenance during production hours. (Which is very useful in something like an ISP where "production hours" are typically 24 hours a day...)