Ever since I started with Vyatta, I've had a problem with commands for features unrelated to interfaces being defined inside interfaces. I'm sure the person who came up with that arrangement meant well and thought it would be familiar for Cisco and Juniper users, but the more I lived with it, the more I thought it creates more problems than it solves.



From the user perspective, it's hard to easily view the complete configuration of those features. It's also much harder to clone a feature config to another machine. And if you ever want to move some connection to a different NIC, things get even more fun.

For developers, however, it's even worse. First, it means commands for those features needs to be duplicated for every interface type, which makes adding new interfaces much harder. Second, configuration scripts end up more complex due to paths that can be nested quite deeply. Third, with the current config backend specifically, lack of nested end nodes can lead to very interesting tracking of the state to avoid repeated service restarts.



Until recently there was a token excuse for leaving unfortunate UI decisions alone — the difficulty of writing migration scripts. Luckily, it's no longer the case, so we can start cleaning it up. Ok, it is hard and you need to take care of many details, but at least you are not wrestling with a library that is simply inadequate for the task. Now we can go on a quest to remove excessive nesting and redesign the UI is an easier to use, more logical fashion.



VRRP looked a good feature to start the clean up with — we need to get IPv6 VRRP support to work in the end, its scripts have accumulated quite some cruft, and, well, it really has nothing to do with interface settings since it's a protocol of its own implemented by a userspace daemon.



Today I've rolled out the new implementation and it is already in the latest rolling release image, ready for your testing. Let's walk through the changes.





Keepalived

Keepalived was updated to version 2.0.5 with some patches of my own that are already in master but not in a release yet.



New VRRP syntax

Here is an example of a VRRP group with all available options set:

dmbaturin@vyos# show high-availability vrrp group WAN

advertise-interval 5

authentication {

password qwerty

type plaintext-password # could also be "ah"

}

description "My VRRP group"

disable

health-check {

failure-count 5

interval 60

script /config/scripts/healthcheck.sh

}

hello-source-address 10.218.0.1

interface eth1

no-preempt

peer-address 10.218.0.10

preempt-delay 180

priority 200

rfc3768-compatibility

transition-script {

backup /config/scripts/backup.sh

fault /config/scripts/fault.sh

master /config/scripts/master.sh

}

virtual-address 10.218.0.100/24

virtual-address 10.218.0.101/24

vrid 42

As you can see, instead of being nested inside interfaces, VRRP has its own subtree now, "set high-availability vrrp". This makes it easy to move a VRRP group to a different interface, or change its VRID (Virtual Router ID) without resorting to node renaming or deleting and recreating it.



Originally, group number used to define the VRID, as in, "set interfaces ethernet eth0 vrrp vrrp-group 10" would create a group with VRID 10. Now group names are purely for identification and can be arbitrary. To set the VRID, use the "vrid" option.

Since groups are now outside of interfaces, the interface is also an option, that can be changed easily. The interfaces you can use are ethernet, bonding, bridge, and VLANs (including QinQ VLANs) on all of those.

Otherwise the options inside the groups changed little. The option that controls preempt mode is now a valueless node "no-preempt" rather than a boolean node "preempt (true|false)". The "run-transition-scripts" option is now simply "transition-script" — after all, what else one could do with them other than run them?

There is one behaviour change that I think no one will notice, but it should be mentioned. The old CLI used to allow setting a virtual-address without prefix length, as in "virtual-address 192.0.2.1". I think it was an oversight, because it could trick people into thinking it will have the same prefix length as the primary address of the interface, but it's not the case. Instead, the prefix length of such addresses would be set to /32, which, in broadcast networks, makes little sense. Now the CLI requires that you specify prefix length. If you relly want a virtual address with /32 or /128 mask, you should specify it explicitly.

Sync groups

You might have already noticed that sync-group option is missing, even though I said that group has all available options set. That's right — sync groups are now separate entities. This is how you can create one:

dmbaturin@vyos# show high-availability vrrp sync-group

sync-group MySyncGroup {

member WAN

member LAN

}

Unlike the old CLI, it's very easy to see which sync groups exist in the system, and shuffle VRRP groups between them if necessary.

IPv6 support

I'm pretty sure it's going to be everyone's first question, and rightfully so! The short answer is: yes, IPv6 VRRP is here for real. The long answer: with one caveat, you cannot mix IPv4 and IPv6 in one group.

This is a keepalived limitation. The VRRP protocol specification technically allows it, which is why I didn't make separate syntax for IPv6 groups. Maybe the restriction will be relaxed at some point, maybe not. Right now, if you try to mix IPv4 and IPv6 addresses in one group, you'll get a commit error.

dmbaturin@vyos# show interfaces ethernet eth1

address 10.218.0.1/24

address 2001:db8:ee::1/64

duplex auto

hw-id 00:50:56:9b:9d:9f

smp-affinity auto

speed auto

[edit]

dmbaturin@vyos# show high-availability

vrrp {

group IPv4 {

interface eth1

virtual-address 10.218.0.2/24

vrid 44

}

group IPv6 {

interface eth1

virtual-address 2001:db8:ee::2/64

vrid 43

}

}

[edit]

dmbaturin@vyos# run show interfaces ethernet eth1

eth1: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000

link/ether 00:50:56:9b:9d:9f brd ff:ff:ff:ff:ff:ff

inet 10.218.0.1/24 brd 10.218.0.255 scope global eth1

valid_lft forever preferred_lft forever

inet 10.218.0.2/24 scope global secondary eth1

valid_lft forever preferred_lft forever

inet6 2001:db8:ee::2/64 scope global nodad

valid_lft forever preferred_lft forever

inet6 2001:db8:ee::1/64 scope global

valid_lft forever preferred_lft forever

Operational mode commands

The essentials are implemented, but it's subject to expansion and improvement.

These commands are already there:

show vrrp

show vrrp detail

show vrrp statistics The output of "show vrrp" has changed a bit, some hardly informative fields such as "addr owner" (which has little practical implications) were removed.

dmbaturin@vyos# run show vrrp

Name Interface VRID State Last Transition

------ ----------- ------ ------- -----------------

Foo eth1 30 MASTER 4s

Lack of information about sync group membership is a more significant omission and if there's demand for it, I'll try to get it back. The reason for it is that the new op mode uses keepalived's JSON output implemented in recent versions, but that output lacks some information that was included in the old (hard to parse) format, so I'll need to send them a patch for it.

Transition scripts

The order of transition script arguments remains compatible. One difference is that for RFC-compliant (i.e. using a macvlan for virtual MAC) VRRP, transition scripts now receive the macvlan interface where addresses are actually assigneg, e.g. eth1v43.

Compatibility with old configs

To ensure compatibility with old configs, I've written a migration script that should cover both configs from 1.1.8 and from earlier versions of the rolling release (including unicast peer and health-check options).

Your old configs should be automatically converted to the new syntax after image updgrade.

Your testing is needed!

The code is new, and there may be corner cases I've missed. If you find any bugs, please report them!





