radvd icon indicating copy to clipboard operation
radvd copied to clipboard

BSD: Check MASTER/BACKUP of link-local addresses configured in AdvRASrcAddress

Open znerol opened this issue 2 years ago • 4 comments

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

znerol avatar Dec 11 '21 12:12 znerol

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.

robbat2 avatar Dec 15 '21 06:12 robbat2

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

sjorge avatar Dec 15 '21 13:12 sjorge

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.

robbat2 avatar Dec 15 '21 16:12 robbat2

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.

  1. Extract ifi_vhid from the ifa_data field of a given struct ifaddrs. Example:
	/* Set the vhid */
	if (ifa->ifa_data) {
		addr->vhid = ((struct if_data *)ifa->ifa_data)->ifi_vhid;
	}
  1. Compare that with info retrieved using the SIOCGVH ioctl. 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.

znerol avatar Dec 15 '21 17:12 znerol