summaryrefslogtreecommitdiffstats
path: root/vrrpd/vrrp.c
diff options
context:
space:
mode:
authorQuentin Young <qlyoung@cumulusnetworks.com>2019-03-08 19:30:03 +0100
committerQuentin Young <qlyoung@cumulusnetworks.com>2019-05-17 02:27:08 +0200
commit1760ce424b642c8ac9e7d4db72f9346533da1f98 (patch)
tree9cd6e18609e9d15eddbc0eff10b855d0c9e0023f /vrrpd/vrrp.c
parentRevert "vrrpd: protodown mvlans when shutting down" (diff)
downloadfrr-1760ce424b642c8ac9e7d4db72f9346533da1f98.tar.xz
frr-1760ce424b642c8ac9e7d4db72f9346533da1f98.zip
vrrpd: allow OS to choose VRRP IPv6 src address
Under IPv6, Linux will look at our destination address and select the source address with the smallest scope that covers the destination. For the VRRP multicast address ff02::12, Linux will always select a link local address. We can take advantage of this behavior to avoid a subtle and complicated class of bugs caused by Zebra's semantics around inoperative interfaces. As far as Zebra is concerned, an inoperative interface has no addresses assigned to it. This is a real bummer for VRRP because it's quite possible that the IPv6 VRRP macvlan device is down when we attach to it, and we would really like to be able to know in advance which address we will be transmitting IPv6 advertisements from without having to bring an interface up to convince Zebra to tell us its address list. In the future, though, it would be better to be explicit about selecting the link local we want. This will require adding the ability to Zebra to read and send us address information for inoperative interfaces. Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
Diffstat (limited to 'vrrpd/vrrp.c')
-rw-r--r--vrrpd/vrrp.c15
1 files changed, 8 insertions, 7 deletions
diff --git a/vrrpd/vrrp.c b/vrrpd/vrrp.c
index cba078a6c..6262cd692 100644
--- a/vrrpd/vrrp.c
+++ b/vrrpd/vrrp.c
@@ -315,10 +315,10 @@ void vrrp_check_start(struct vrrp_vrouter *vr)
#if 0
/* Macvlan interface must be admin up */
start = start && CHECK_FLAG(r->mvl_ifp->flags, IFF_UP);
-#endif
/* Macvlan interface must have a link local */
start = start && connected_get_linklocal(r->mvl_ifp);
whynot = (!start && !whynot) ? "No link local address configured" : NULL;
+#endif
/* Macvlan interface must have a v6 IP besides the link local */
start = start && (r->mvl_ifp->connected->count >= 2);
whynot = (!start && !whynot) ? "No Virtual IP address configured" : NULL;
@@ -1125,6 +1125,13 @@ static int vrrp_socket(struct vrrp_router *r)
VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
"Set %s as outgoing multicast interface",
r->vr->vrid, family2str(r->family), r->mvl_ifp->name);
+
+ /* Select and bind source address */
+ if (vrrp_bind_to_primary_connected(r) < 0) {
+ failed = true;
+ goto done;
+ }
+
} else if (r->family == AF_INET6) {
/* Always transmit IPv6 packets with hop limit set to 255 */
ret = setsockopt_ipv6_multicast_hops(r->sock_tx, 255);
@@ -1227,12 +1234,6 @@ static int vrrp_socket(struct vrrp_router *r)
r->vr->vrid, family2str(r->family), r->mvl_ifp->name);
}
- /* Bind Tx socket to link-local address */
- if (vrrp_bind_to_primary_connected(r) < 0) {
- failed = true;
- goto done;
- }
-
done:
ret = 0;
if (failed) {