BSD: Check MASTER/BACKUP of link-local addresses configured in AdvRASrcAddress
In HA setups as outlined in this post, radvd is concurrently running on multiple routers. RAs are only sent out on an interface iff the link local address configured via AdvRASrcAddress is present on the specified interface.
This works well on Linux because Keepalived makes sure that the virtual link-local address is configured on one node only. In BSD/CARP however, a virtual CARP address is always configured on all nodes. It is just flagged with MASTER/BACKUP.
Running radvd on multiple BSD routers in aforementioned HA mode currently results in all routers (primary as well as backups) sending out RAs regardless of their current HA role.
In order to resolve this issue, radvd needs to be extended to respect MASTER/BACKUP flags on virtual link-local address on BSDs and only send out RAs iff an address configured via AdvRASrcAddress is flagged as MASTER.
Related issues in pfSense:
- https://redmine.pfsense.org/issues/11103
- https://redmine.pfsense.org/issues/12582
Do you have good examples of how to check those flags in BSD? I'd never run into them before today.
It does strike me as a good extension to VRRP, making the kernel aware of the address state, but this would be BSD-specific changes to guard w/ ifdefs.
I actually found this issue today because I was trying to figure out how to get the failover node to not announce...
I'm not really a C or derivatives programmer but I was messing around with ppp_thing which is a PPPoE client that works over CARP that shares a session between nodes.
Not sure how useful this or if the BSD3-clause source license of ppp_thing is even compatible with radvd, but the check to see if the host is the CARP master seem to be here: https://github.com/russor/ppp_thing/blob/main/ppp_thing.c#L148
That just tries to put routes via netlink and assumes if they succeed that it's using CARP and it's MASTER, which i'm not sure is safe.
Disclaimer, I am not a BSD developer.. Please take the following analysis with a grain of salt.
Two steps are necessary to check the state of a given address.
- Extract
ifi_vhidfrom theifa_datafield of a givenstruct ifaddrs. Example:
/* Set the vhid */
if (ifa->ifa_data) {
addr->vhid = ((struct if_data *)ifa->ifa_data)->ifi_vhid;
}
- Compare that with info retrieved using the
SIOCGVHioctl. See ifconfig_carp_get_info and carp_status.
All of this is implemented in libifconfig in FreeBSD.
OpenBSD seems to be using the same mechanism (SIOCGVH) but doesn't have those methods extracted to a library. Everything is implemented directly in ifconfig.c.