2 * VRRP global definitions and state machine.
3 * Copyright (C) 2018-2019 Cumulus Networks, Inc.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "lib/linklist.h"
26 #include "lib/memory.h"
27 #include "lib/network.h"
28 #include "lib/prefix.h"
29 #include "lib/sockopt.h"
30 #include "lib/sockunion.h"
36 #include "vrrp_debug.h"
37 #include "vrrp_ndisc.h"
38 #include "vrrp_packet.h"
39 #include "vrrp_zebra.h"
41 #define VRRP_LOGPFX "[CORE] "
43 DEFINE_MTYPE_STATIC(VRRPD
, VRRP_IP
, "VRRP IP address")
44 DEFINE_MTYPE_STATIC(VRRPD
, VRRP_RTR
, "VRRP Router")
47 struct hash
*vrrp_vrouters_hash
;
48 bool vrrp_autoconfig_is_on
;
49 int vrrp_autoconfig_version
;
51 struct vrrp_defaults vd
;
53 const char *const vrrp_state_names
[3] = {
54 [VRRP_STATE_INITIALIZE
] = "Initialize",
55 [VRRP_STATE_MASTER
] = "Master",
56 [VRRP_STATE_BACKUP
] = "Backup",
59 static const char *const vrrp_event_names
[2] = {
60 [VRRP_EVENT_STARTUP
] = "Startup",
61 [VRRP_EVENT_SHUTDOWN
] = "Shutdown",
65 /* Utility functions ------------------------------------------------------- */
68 * Sets an ethaddr to RFC-defined Virtual Router MAC address.
74 * Whether this is a V6 or V4 Virtual Router MAC
77 * Virtual Router Identifier
79 static void vrrp_mac_set(struct ethaddr
*mac
, bool v6
, uint8_t vrid
)
82 * V4: 00-00-5E-00-01-{VRID}
83 * V6: 00-00-5E-00-02-{VRID}
89 mac
->octet
[4] = v6
? 0x02 : 0x01;
94 * Recalculates and sets skew_time and master_down_interval based
98 * VRRP Router to operate on
100 static void vrrp_recalculate_timers(struct vrrp_router
*r
)
102 uint16_t mdiadv
= r
->vr
->version
== 3 ? r
->master_adver_interval
103 : r
->vr
->advertisement_interval
;
104 uint16_t skm
= (r
->vr
->version
== 3) ? r
->master_adver_interval
: 100;
106 r
->skew_time
= ((256 - r
->vr
->priority
) * skm
) / 256;
107 r
->master_down_interval
= 3 * mdiadv
;
108 r
->master_down_interval
+= r
->skew_time
;
112 * Determines if a VRRP router is the owner of the specified address.
114 * The determining factor for whether an interface is the address owner is
115 * simply whether the address is assigned to the VRRP base interface by someone
118 * This function should always return the correct answer regardless of
119 * master/backup status.
122 * The interface to check owernship of. This should be the base interface of
129 * whether or not vr owns the specified address
131 static bool vrrp_is_owner(struct interface
*ifp
, struct ipaddr
*addr
)
134 * This code sanity checks implicit ownership configuration. Ideally,
135 * the way we determine address ownership status for this VRRP router
136 * is by looking at whether our VIPs are also assigned to the base
137 * interface, and therefore count as "real" addresses. This frees the
138 * user from having to manually configure priority 255 to indicate
139 * address ownership. However, this means one of the VIPs will be used
140 * as the source address for VRRP advertisements, which in turn means
141 * that other VRRP routers will be receiving packets with a source
142 * address they themselves have. This causes lots of different issues
143 * so for now we're disabling this and forcing the user to configure
144 * priority 255 to indicate ownership.
152 p
.family
= IS_IPADDR_V4(addr
) ? AF_INET
: AF_INET6
;
153 p
.prefixlen
= IS_IPADDR_V4(addr
) ? IPV4_MAX_BITLEN
: IPV6_MAX_BITLEN
;
154 memcpy(&p
.u
, &addr
->ip
, sizeof(addr
->ip
));
156 return !!connected_lookup_prefix_exact(ifp
, &p
);
161 * Whether an interface has a MAC address that matches the VRRP RFC.
167 * Whether the interface has a VRRP mac or not
169 static bool vrrp_ifp_has_vrrp_mac(struct interface
*ifp
)
171 struct ethaddr vmac4
;
172 struct ethaddr vmac6
;
174 vrrp_mac_set(&vmac4
, 0, 0x00);
175 vrrp_mac_set(&vmac6
, 1, 0x00);
177 return !memcmp(ifp
->hw_addr
, vmac4
.octet
, sizeof(vmac4
.octet
) - 1)
178 || !memcmp(ifp
->hw_addr
, vmac6
.octet
, sizeof(vmac6
.octet
) - 1);
182 * Lookup a Virtual Router instance given a macvlan subinterface.
184 * The VRID is extracted from the interface MAC and the 2-tuple (iface, vrid)
185 * is used to look up any existing instances that match the interface. It does
186 * not matter whether the instance is already bound to the interface or not.
188 * Note that the interface linkages must be correct for this to work. In other
189 * words, the macvlan must have a valid VRRP MAC, and its link_ifindex must be
190 * be equal to the ifindex of another interface in the interface RB trees (its
191 * parent). If these conditions aren't satisfied we won't find the VR.
194 * Interface pointer to use to lookup. Should be a macvlan device.
197 * Virtual Router, if found
200 static struct vrrp_vrouter
*vrrp_lookup_by_if_mvl(struct interface
*mvl_ifp
)
204 if (!mvl_ifp
|| mvl_ifp
->link_ifindex
== 0
205 || !vrrp_ifp_has_vrrp_mac(mvl_ifp
)) {
206 if (mvl_ifp
&& mvl_ifp
->link_ifindex
== 0)
207 DEBUGD(&vrrp_dbg_zebra
,
209 "Interface %s has no parent ifindex; disregarding",
211 if (mvl_ifp
&& !vrrp_ifp_has_vrrp_mac(mvl_ifp
))
212 DEBUGD(&vrrp_dbg_zebra
,
214 "Interface %s has a non-VRRP MAC; disregarding",
219 p
= if_lookup_by_index(mvl_ifp
->link_ifindex
, mvl_ifp
->vrf_id
);
222 DEBUGD(&vrrp_dbg_zebra
,
224 "Tried to lookup interface %d, parent of %s, but it doesn't exist",
225 mvl_ifp
->link_ifindex
, mvl_ifp
->name
);
229 uint8_t vrid
= mvl_ifp
->hw_addr
[5];
231 return vrrp_lookup(p
, vrid
);
235 * Lookup the Virtual Router instances configured on a particular interface.
238 * Interface pointer to use to lookup. Should not be a macvlan device.
241 * List of virtual routers found
243 static struct list
*vrrp_lookup_by_if(struct interface
*ifp
)
245 struct list
*l
= hash_to_list(vrrp_vrouters_hash
);
246 struct listnode
*ln
, *nn
;
247 struct vrrp_vrouter
*vr
;
249 for (ALL_LIST_ELEMENTS(l
, ln
, nn
, vr
))
251 list_delete_node(l
, ln
);
257 * Lookup any Virtual Router instances associated with a particular interface.
258 * This is a combination of the results from vrrp_lookup_by_if_mvl and
261 * Suppose the system interface list looks like the following:
264 * \- eth0-v0 00:00:5e:00:01:01
265 * \- eth0-v1 00:00:5e:00:02:01
266 * \- eth0-v2 00:00:5e:00:01:0a
268 * Passing eth0-v2 to this function will give you the VRRP instance configured
269 * on eth0 with VRID 10. Passing eth0-v0 or eth0-v1 will give you the VRRP
270 * instance configured on eth0 with VRID 1. Passing eth0 will give you both.
273 * Interface pointer to use to lookup. Can be any interface.
276 * List of virtual routers found
278 static struct list
*vrrp_lookup_by_if_any(struct interface
*ifp
)
280 struct vrrp_vrouter
*vr
;
283 vr
= vrrp_lookup_by_if_mvl(ifp
);
284 vrs
= vr
? list_new() : vrrp_lookup_by_if(ifp
);
287 listnode_add(vrs
, vr
);
292 /* Configuration controllers ----------------------------------------------- */
294 void vrrp_check_start(struct vrrp_vrouter
*vr
)
296 struct vrrp_router
*r
;
298 const char *whynot
= NULL
;
300 if (vr
->shutdown
|| vr
->ifp
== NULL
)
304 /* Must not already be started */
305 start
= r
->fsm
.state
== VRRP_STATE_INITIALIZE
;
306 whynot
= (!start
&& !whynot
) ? "Already running" : whynot
;
307 /* Must have a parent interface */
308 start
= start
&& (vr
->ifp
!= NULL
);
309 whynot
= (!start
&& !whynot
) ? "No base interface" : whynot
;
311 /* Parent interface must be up */
312 start
= start
&& if_is_operative(vr
->ifp
);
313 start
= (!start
&& !whynot
) ? "Base interface inoperative" : whynot
;
315 /* Parent interface must have at least one v4 */
316 start
= start
&& connected_count_by_family(vr
->ifp
, AF_INET
) > 0;
317 whynot
= (!start
&& !whynot
) ? "No primary IPv4 address" : whynot
;
318 /* Must have a macvlan interface */
319 start
= start
&& (r
->mvl_ifp
!= NULL
);
320 whynot
= (!start
&& !whynot
) ? "No VRRP interface" : whynot
;
322 /* Macvlan interface must be admin up */
323 start
= start
&& CHECK_FLAG(r
->mvl_ifp
->flags
, IFF_UP
);
324 start
= (!start
&& !whynot
) ? "Macvlan device admin down" : whynot
;
326 /* Must have at least one VIP configured */
327 start
= start
&& r
->addrs
->count
> 0;
328 whynot
= (!start
&& !whynot
) ? "No Virtual IP address configured"
331 vrrp_event(r
, VRRP_EVENT_STARTUP
);
333 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
334 "Refusing to start Virtual Router: %s",
335 vr
->vrid
, family2str(r
->family
), whynot
);
340 /* Must not already be started */
341 start
= r
->fsm
.state
== VRRP_STATE_INITIALIZE
;
342 whynot
= (!start
&& !whynot
) ? "Already running" : whynot
;
344 start
= start
&& vr
->version
!= 2;
345 whynot
= (!start
&& !whynot
) ? "VRRPv2 does not support v6" : whynot
;
346 /* Must have a parent interface */
347 start
= start
&& (vr
->ifp
!= NULL
);
348 whynot
= (!start
&& !whynot
) ? "No base interface" : whynot
;
350 /* Parent interface must be up */
351 start
= start
&& if_is_operative(vr
->ifp
);
352 start
= (!start
&& !whynot
) ? "Base interface inoperative" : whynot
;
354 /* Must have a macvlan interface */
355 start
= start
&& (r
->mvl_ifp
!= NULL
);
356 whynot
= (!start
&& !whynot
) ? "No VRRP interface" : whynot
;
358 /* Macvlan interface must be admin up */
359 start
= start
&& CHECK_FLAG(r
->mvl_ifp
->flags
, IFF_UP
);
360 start
= (!start
&& !whynot
) ? "Macvlan device admin down" : whynot
;
361 /* Macvlan interface must have a link local */
362 start
= start
&& connected_get_linklocal(r
->mvl_ifp
);
364 (!start
&& !whynot
) ? "No link local address configured" : whynot
;
365 /* Macvlan interface must have a v6 IP besides the link local */
366 start
= start
&& (connected_count_by_family(r
->mvl_ifp
, AF_INET6
) > 1);
367 whynot
= (!start
&& !whynot
)
368 ? "No Virtual IPv6 address configured on macvlan device"
371 /* Must have at least one VIP configured */
372 start
= start
&& r
->addrs
->count
> 0;
374 (!start
&& !whynot
) ? "No Virtual IP address configured" : whynot
;
376 vrrp_event(r
, VRRP_EVENT_STARTUP
);
378 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
379 "Refusing to start Virtual Router: %s",
380 vr
->vrid
, family2str(r
->family
), whynot
);
383 void vrrp_set_priority(struct vrrp_vrouter
*vr
, uint8_t priority
)
385 vr
->priority
= priority
;
386 vr
->v4
->priority
= priority
;
387 vr
->v6
->priority
= priority
;
390 void vrrp_set_advertisement_interval(struct vrrp_vrouter
*vr
,
391 uint16_t advertisement_interval
)
393 if (vr
->advertisement_interval
== advertisement_interval
)
396 vr
->advertisement_interval
= advertisement_interval
;
397 vrrp_recalculate_timers(vr
->v4
);
398 vrrp_recalculate_timers(vr
->v6
);
401 static bool vrrp_has_ip(struct vrrp_vrouter
*vr
, struct ipaddr
*ip
)
403 struct vrrp_router
*r
= ip
->ipa_type
== IPADDR_V4
? vr
->v4
: vr
->v6
;
407 for (ALL_LIST_ELEMENTS_RO(r
->addrs
, ln
, iter
))
408 if (!memcmp(&iter
->ip
, &ip
->ip
, IPADDRSZ(ip
)))
414 int vrrp_add_ip(struct vrrp_vrouter
*vr
, struct ipaddr
*ip
)
416 struct vrrp_router
*r
= IS_IPADDR_V4(ip
) ? vr
->v4
: vr
->v6
;
419 assert(r
->family
== af
);
420 assert(!(r
->vr
->version
== 2 && ip
->ipa_type
== IPADDR_V6
));
422 if (vrrp_has_ip(r
->vr
, ip
))
425 if (!vrrp_is_owner(r
->vr
->ifp
, ip
) && r
->is_owner
) {
426 char ipbuf
[INET6_ADDRSTRLEN
];
428 inet_ntop(r
->family
, &ip
->ip
, ipbuf
, sizeof(ipbuf
));
430 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
431 "This VRRP router is not the address owner of %s, but is the address owner of other addresses; this config is unsupported.",
432 r
->vr
->vrid
, family2str(r
->family
), ipbuf
);
436 struct ipaddr
*new = XCALLOC(MTYPE_VRRP_IP
, sizeof(struct ipaddr
));
439 listnode_add(r
->addrs
, new);
441 if (r
->fsm
.state
== VRRP_STATE_MASTER
) {
444 vrrp_garp_send(r
, &new->ipaddr_v4
);
447 vrrp_ndisc_una_send(r
, new);
455 int vrrp_add_ipv4(struct vrrp_vrouter
*vr
, struct in_addr v4
)
459 ip
.ipa_type
= IPADDR_V4
;
461 return vrrp_add_ip(vr
, &ip
);
464 int vrrp_add_ipv6(struct vrrp_vrouter
*vr
, struct in6_addr v6
)
466 assert(vr
->version
!= 2);
470 ip
.ipa_type
= IPADDR_V6
;
472 return vrrp_add_ip(vr
, &ip
);
475 int vrrp_del_ip(struct vrrp_vrouter
*vr
, struct ipaddr
*ip
)
477 struct listnode
*ln
, *nn
;
481 struct vrrp_router
*r
= IS_IPADDR_V4(ip
) ? vr
->v4
: vr
->v6
;
483 if (!vrrp_has_ip(r
->vr
, ip
))
486 for (ALL_LIST_ELEMENTS(r
->addrs
, ln
, nn
, iter
))
487 if (!memcmp(&iter
->ip
, &ip
->ip
, IPADDRSZ(ip
)))
488 list_delete_node(r
->addrs
, ln
);
491 * NB: Deleting the last address and then issuing a shutdown will cause
492 * transmission of a priority 0 VRRP Advertisement - as per the RFC -
493 * but it will have no addresses. This is not forbidden in the RFC but
494 * might confuse other implementations.
496 if (r
->addrs
->count
== 0 && r
->fsm
.state
!= VRRP_STATE_INITIALIZE
)
497 ret
= vrrp_event(r
, VRRP_EVENT_SHUTDOWN
);
502 int vrrp_del_ipv6(struct vrrp_vrouter
*vr
, struct in6_addr v6
)
506 ip
.ipa_type
= IPADDR_V6
;
508 return vrrp_del_ip(vr
, &ip
);
511 int vrrp_del_ipv4(struct vrrp_vrouter
*vr
, struct in_addr v4
)
515 ip
.ipa_type
= IPADDR_V4
;
517 return vrrp_del_ip(vr
, &ip
);
521 /* Creation and destruction ------------------------------------------------ */
523 static void vrrp_router_addr_list_del_cb(void *val
)
525 struct ipaddr
*ip
= val
;
527 XFREE(MTYPE_VRRP_IP
, ip
);
531 * Search for a suitable macvlan subinterface we can attach to, and if found,
535 * Router to attach to interface
538 * Whether an interface was successfully attached
540 static bool vrrp_attach_interface(struct vrrp_router
*r
)
542 /* Search for existing interface with computed MAC address */
543 struct interface
**ifps
;
546 if_lookup_by_hwaddr(r
->vmac
.octet
, sizeof(r
->vmac
.octet
), &ifps
,
550 * Filter to only those macvlan interfaces whose parent is the base
551 * interface this VRRP router is configured on.
553 * If there are still multiple interfaces we just select the first one,
554 * as it should be functionally identical to the others.
556 unsigned int candidates
= 0;
557 struct interface
*selection
= NULL
;
559 for (unsigned int i
= 0; i
< ifps_cnt
; i
++) {
560 if (ifps
[i
]->link_ifindex
!= r
->vr
->ifp
->ifindex
)
563 selection
= selection
? selection
: ifps
[i
];
569 XFREE(MTYPE_TMP
, ifps
);
571 char ethstr
[ETHER_ADDR_STRLEN
];
573 prefix_mac2str(&r
->vmac
, ethstr
, sizeof(ethstr
));
575 assert(!!selection
== !!candidates
);
578 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
579 "Interface: None (no interface found w/ MAC %s)",
580 r
->vr
->vrid
, family2str(r
->family
), ethstr
);
581 else if (candidates
> 1)
582 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
583 "Interface: Multiple interfaces found; using %s",
584 r
->vr
->vrid
, family2str(r
->family
), selection
->name
);
586 zlog_info(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
588 r
->vr
->vrid
, family2str(r
->family
), selection
->name
);
590 r
->mvl_ifp
= selection
;
595 static struct vrrp_router
*vrrp_router_create(struct vrrp_vrouter
*vr
,
598 struct vrrp_router
*r
=
599 XCALLOC(MTYPE_VRRP_RTR
, sizeof(struct vrrp_router
));
605 r
->addrs
= list_new();
606 r
->addrs
->del
= vrrp_router_addr_list_del_cb
;
607 r
->priority
= vr
->priority
;
608 r
->fsm
.state
= VRRP_STATE_INITIALIZE
;
609 vrrp_mac_set(&r
->vmac
, family
== AF_INET6
, vr
->vrid
);
611 vrrp_attach_interface(r
);
616 static void vrrp_router_destroy(struct vrrp_router
*r
)
619 vrrp_event(r
, VRRP_EVENT_SHUTDOWN
);
626 /* FIXME: also delete list elements */
627 list_delete(&r
->addrs
);
628 XFREE(MTYPE_VRRP_RTR
, r
);
631 struct vrrp_vrouter
*vrrp_vrouter_create(struct interface
*ifp
, uint8_t vrid
,
634 struct vrrp_vrouter
*vr
= vrrp_lookup(ifp
, vrid
);
639 if (version
!= 2 && version
!= 3)
642 vr
= XCALLOC(MTYPE_VRRP_RTR
, sizeof(struct vrrp_vrouter
));
645 vr
->version
= version
;
647 vr
->priority
= vd
.priority
;
648 vr
->preempt_mode
= vd
.preempt_mode
;
649 vr
->accept_mode
= vd
.accept_mode
;
650 vr
->shutdown
= vd
.shutdown
;
652 vr
->v4
= vrrp_router_create(vr
, AF_INET
);
653 vr
->v6
= vrrp_router_create(vr
, AF_INET6
);
655 vrrp_set_advertisement_interval(vr
, vd
.advertisement_interval
);
657 hash_get(vrrp_vrouters_hash
, vr
, hash_alloc_intern
);
662 void vrrp_vrouter_destroy(struct vrrp_vrouter
*vr
)
664 vrrp_router_destroy(vr
->v4
);
665 vrrp_router_destroy(vr
->v6
);
666 hash_release(vrrp_vrouters_hash
, vr
);
667 XFREE(MTYPE_VRRP_RTR
, vr
);
670 struct vrrp_vrouter
*vrrp_lookup(const struct interface
*ifp
, uint8_t vrid
)
672 struct vrrp_vrouter vr
;
675 vr
.ifp
= (struct interface
*)ifp
;
677 return hash_lookup(vrrp_vrouters_hash
, &vr
);
680 /* Network ----------------------------------------------------------------- */
683 static void vrrp_change_state(struct vrrp_router
*r
, int to
);
684 static int vrrp_adver_timer_expire(struct thread
*thread
);
685 static int vrrp_master_down_timer_expire(struct thread
*thread
);
688 * Finds the first connected address of the appropriate family on a VRRP
689 * router's interface and binds the Tx socket of the VRRP router to that
692 * Also sets src field of vrrp_router.
695 * VRRP router to operate on
701 static int vrrp_bind_to_primary_connected(struct vrrp_router
*r
)
703 struct interface
*ifp
;
706 * A slight quirk: the RFC specifies that advertisements under IPv6 must
707 * be transmitted using the link local address of the source interface
709 ifp
= r
->family
== AF_INET
? r
->vr
->ifp
: r
->mvl_ifp
;
712 struct connected
*c
= NULL
;
714 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, ln
, c
))
715 if (c
->address
->family
== r
->family
) {
716 if (r
->family
== AF_INET6
717 && IN6_IS_ADDR_LINKLOCAL(&c
->address
->u
.prefix6
))
719 else if (r
->family
== AF_INET
)
724 zlog_err(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
725 "Failed to find address to bind on %s",
726 r
->vr
->vrid
, family2str(r
->family
), ifp
->name
);
732 memset(&su
, 0x00, sizeof(su
));
736 r
->src
.ipa_type
= IPADDR_V4
;
737 r
->src
.ipaddr_v4
= c
->address
->u
.prefix4
;
738 su
.sin
.sin_family
= AF_INET
;
739 su
.sin
.sin_addr
= c
->address
->u
.prefix4
;
742 r
->src
.ipa_type
= IPADDR_V6
;
743 r
->src
.ipaddr_v6
= c
->address
->u
.prefix6
;
744 su
.sin6
.sin6_family
= AF_INET6
;
745 su
.sin6
.sin6_scope_id
= ifp
->ifindex
;
746 su
.sin6
.sin6_addr
= c
->address
->u
.prefix6
;
752 sockopt_reuseaddr(r
->sock_tx
);
753 if (bind(r
->sock_tx
, (const struct sockaddr
*)&su
, sizeof(su
)) < 0) {
755 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
756 "Failed to bind Tx socket to primary IP address %pFX: %s",
757 r
->vr
->vrid
, family2str(r
->family
), c
->address
,
758 safe_strerror(errno
));
761 DEBUGD(&vrrp_dbg_sock
,
762 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
763 "Bound Tx socket to primary IP address %pFX",
764 r
->vr
->vrid
, family2str(r
->family
), c
->address
);
772 * Create and multicast a VRRP ADVERTISEMENT message.
775 * VRRP Router for which to send ADVERTISEMENT
777 static void vrrp_send_advertisement(struct vrrp_router
*r
)
779 struct vrrp_pkt
*pkt
;
781 struct ipaddr
*addrs
[r
->addrs
->count
];
782 union sockunion dest
;
784 if (r
->src
.ipa_type
== IPADDR_NONE
785 && vrrp_bind_to_primary_connected(r
) < 0)
788 list_to_array(r
->addrs
, (void **)addrs
, r
->addrs
->count
);
790 pktsz
= vrrp_pkt_adver_build(&pkt
, &r
->src
, r
->vr
->version
, r
->vr
->vrid
,
791 r
->priority
, r
->vr
->advertisement_interval
,
792 r
->addrs
->count
, (struct ipaddr
**)&addrs
);
794 if (DEBUG_MODE_CHECK(&vrrp_dbg_pkt
, DEBUG_MODE_ALL
))
795 zlog_hexdump(pkt
, (size_t)pktsz
);
797 const char *group
= r
->family
== AF_INET
? VRRP_MCASTV4_GROUP_STR
798 : VRRP_MCASTV6_GROUP_STR
;
799 (void)str2sockunion(group
, &dest
);
801 ssize_t sent
= sendto(r
->sock_tx
, pkt
, (size_t)pktsz
, 0, &dest
.sa
,
802 sockunion_sizeof(&dest
));
807 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
808 "Failed to send VRRP Advertisement: %s",
809 r
->vr
->vrid
, family2str(r
->family
),
810 safe_strerror(errno
));
812 ++r
->stats
.adver_tx_cnt
;
817 * Receive and parse VRRP advertisement.
819 * By the time we get here all fields have been validated for basic correctness
820 * and the packet is a valid VRRP packet.
822 * However, we have not validated whether the VRID is correct for this virtual
823 * router, nor whether the priority is correct (i.e. is not 255 when we are the
824 * address owner), nor whether the advertisement interval equals our own
825 * configured value (this check is only performed in VRRPv2).
828 * VRRP Router associated with the socket this advertisement was received on
831 * Source address of sender
834 * The advertisement they sent
837 * Size of advertisement
840 * -1 if advertisement is invalid
843 static int vrrp_recv_advertisement(struct vrrp_router
*r
, struct ipaddr
*src
,
844 struct vrrp_pkt
*pkt
, size_t pktsize
)
846 char sipstr
[INET6_ADDRSTRLEN
];
847 char dipstr
[INET6_ADDRSTRLEN
];
849 ipaddr2str(src
, sipstr
, sizeof(sipstr
));
850 ipaddr2str(&r
->src
, dipstr
, sizeof(dipstr
));
852 char dumpbuf
[BUFSIZ
];
854 vrrp_pkt_adver_dump(dumpbuf
, sizeof(dumpbuf
), pkt
);
855 DEBUGD(&vrrp_dbg_proto
,
856 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
857 "Received VRRP Advertisement from %s: %s",
858 r
->vr
->vrid
, family2str(r
->family
), sipstr
, dumpbuf
);
860 /* Check that VRID matches our configured VRID */
861 if (pkt
->hdr
.vrid
!= r
->vr
->vrid
) {
862 DEBUGD(&vrrp_dbg_proto
,
863 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
864 "Datagram invalid: Advertisement contains VRID %hhu which does not match our instance",
865 r
->vr
->vrid
, family2str(r
->family
), pkt
->hdr
.vrid
);
869 /* Verify that we are not the IPvX address owner */
871 DEBUGD(&vrrp_dbg_proto
,
872 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
873 "Datagram invalid: Received advertisement but we are the address owner",
874 r
->vr
->vrid
, family2str(r
->family
));
878 /* If v2, verify that adver time matches ours */
879 bool adveq
= (pkt
->hdr
.v2
.adver_int
880 == MAX(r
->vr
->advertisement_interval
/ 100, 1));
881 if (r
->vr
->version
== 2 && !adveq
) {
882 DEBUGD(&vrrp_dbg_proto
,
883 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
884 "Datagram invalid: Received advertisement with advertisement interval %hhu unequal to our configured value %u",
885 r
->vr
->vrid
, family2str(r
->family
),
886 pkt
->hdr
.v2
.adver_int
,
887 MAX(r
->vr
->advertisement_interval
/ 100, 1));
892 /* Check that # IPs received matches our # configured IPs */
893 if (pkt
->hdr
.naddr
!= r
->addrs
->count
)
894 DEBUGD(&vrrp_dbg_proto
,
895 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
896 "Datagram has %hhu addresses, but this VRRP instance has %u",
897 r
->vr
->vrid
, family2str(r
->family
), pkt
->hdr
.naddr
,
900 ++r
->stats
.adver_rx_cnt
;
904 switch (r
->fsm
.state
) {
905 case VRRP_STATE_MASTER
:
906 addrcmp
= memcmp(&src
->ip
, &r
->src
.ip
, IPADDRSZ(src
));
908 if (pkt
->hdr
.priority
== 0) {
909 vrrp_send_advertisement(r
);
910 THREAD_OFF(r
->t_adver_timer
);
911 thread_add_timer_msec(
912 master
, vrrp_adver_timer_expire
, r
,
913 r
->vr
->advertisement_interval
* CS2MS
,
915 } else if (pkt
->hdr
.priority
> r
->priority
916 || ((pkt
->hdr
.priority
== r
->priority
)
919 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
920 "Received advertisement from %s w/ priority %hhu; switching to Backup",
921 r
->vr
->vrid
, family2str(r
->family
), sipstr
,
923 THREAD_OFF(r
->t_adver_timer
);
924 if (r
->vr
->version
== 3) {
925 r
->master_adver_interval
=
926 htons(pkt
->hdr
.v3
.adver_int
);
928 vrrp_recalculate_timers(r
);
929 THREAD_OFF(r
->t_master_down_timer
);
930 thread_add_timer_msec(master
,
931 vrrp_master_down_timer_expire
, r
,
932 r
->master_down_interval
* CS2MS
,
933 &r
->t_master_down_timer
);
934 vrrp_change_state(r
, VRRP_STATE_BACKUP
);
936 /* Discard advertisement */
937 DEBUGD(&vrrp_dbg_proto
,
938 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
939 "Discarding advertisement from %s (%hhu <= %hhu & %s <= %s)",
940 r
->vr
->vrid
, family2str(r
->family
), sipstr
,
941 pkt
->hdr
.priority
, r
->priority
, sipstr
, dipstr
);
944 case VRRP_STATE_BACKUP
:
945 if (pkt
->hdr
.priority
== 0) {
946 THREAD_OFF(r
->t_master_down_timer
);
947 thread_add_timer_msec(
948 master
, vrrp_master_down_timer_expire
, r
,
949 r
->skew_time
* CS2MS
, &r
->t_master_down_timer
);
950 } else if (!r
->vr
->preempt_mode
951 || pkt
->hdr
.priority
>= r
->priority
) {
952 if (r
->vr
->version
== 3) {
953 r
->master_adver_interval
=
954 ntohs(pkt
->hdr
.v3
.adver_int
);
956 vrrp_recalculate_timers(r
);
957 THREAD_OFF(r
->t_master_down_timer
);
958 thread_add_timer_msec(master
,
959 vrrp_master_down_timer_expire
, r
,
960 r
->master_down_interval
* CS2MS
,
961 &r
->t_master_down_timer
);
962 } else if (r
->vr
->preempt_mode
963 && pkt
->hdr
.priority
< r
->priority
) {
964 /* Discard advertisement */
965 DEBUGD(&vrrp_dbg_proto
,
966 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
967 "Discarding advertisement from %s (%hhu < %hhu & preempt = true)",
968 r
->vr
->vrid
, family2str(r
->family
), sipstr
,
969 pkt
->hdr
.priority
, r
->priority
);
972 case VRRP_STATE_INITIALIZE
:
973 zlog_err(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
974 "Received ADVERTISEMENT in state %s; this is a bug",
975 r
->vr
->vrid
, family2str(r
->family
),
976 vrrp_state_names
[r
->fsm
.state
]);
984 * Read and process next IPvX datagram.
986 static int vrrp_read(struct thread
*thread
)
988 struct vrrp_router
*r
= thread
->arg
;
990 struct vrrp_pkt
*pkt
;
995 struct sockaddr_storage sa
;
997 struct ipaddr src
= {};
999 struct msghdr m
= {};
1002 iov
.iov_base
= r
->ibuf
;
1003 iov
.iov_len
= sizeof(r
->ibuf
);
1005 m
.msg_namelen
= sizeof(sa
);
1008 m
.msg_control
= control
;
1009 m
.msg_controllen
= sizeof(control
);
1011 nbytes
= recvmsg(r
->sock_rx
, &m
, MSG_DONTWAIT
);
1013 if ((nbytes
< 0 && ERRNO_IO_RETRY(errno
))) {
1016 } else if (nbytes
<= 0) {
1017 vrrp_event(r
, VRRP_EVENT_SHUTDOWN
);
1022 if (DEBUG_MODE_CHECK(&vrrp_dbg_pkt
, DEBUG_MODE_ALL
)) {
1023 DEBUGD(&vrrp_dbg_pkt
,
1024 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1026 r
->vr
->vrid
, family2str(r
->family
));
1027 zlog_hexdump(r
->ibuf
, nbytes
);
1030 pktsize
= vrrp_pkt_parse_datagram(r
->family
, r
->vr
->version
, &m
, nbytes
,
1031 &src
, &pkt
, errbuf
, sizeof(errbuf
));
1034 DEBUGD(&vrrp_dbg_pkt
,
1035 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1036 "Datagram invalid: %s",
1037 r
->vr
->vrid
, family2str(r
->family
), errbuf
);
1039 vrrp_recv_advertisement(r
, &src
, pkt
, pktsize
);
1044 memset(r
->ibuf
, 0x00, sizeof(r
->ibuf
));
1047 thread_add_read(master
, vrrp_read
, r
, r
->sock_rx
, &r
->t_read
);
1053 * Creates and configures VRRP router sockets.
1056 * - Creates two sockets, one for Tx, one for Rx
1057 * - Binds the Tx socket to the macvlan device, if necessary (VRF case)
1058 * - Binds the Rx socket to the base interface
1059 * - Joins the Rx socket to the appropriate VRRP multicast group
1060 * - Sets the Tx socket to set the TTL (v4) or Hop Limit (v6) field to 255 for
1061 * all transmitted IPvX packets
1062 * - Requests the kernel to deliver IPv6 header values needed to validate VRRP
1065 * If any of the above fail, the sockets are closed. The only exception is if
1066 * the TTL / Hop Limit settings fail; these are logged, but configuration
1069 * The first connected address on the Virtual Router's interface is used as the
1070 * interface address.
1073 * VRRP Router for which to create listen socket
1079 static int vrrp_socket(struct vrrp_router
*r
)
1082 bool failed
= false;
1084 frr_with_privs(&vrrp_privs
) {
1085 r
->sock_rx
= vrf_socket(r
->family
, SOCK_RAW
, IPPROTO_VRRP
,
1086 r
->vr
->ifp
->vrf_id
, NULL
);
1087 r
->sock_tx
= vrf_socket(r
->family
, SOCK_RAW
, IPPROTO_VRRP
,
1088 r
->vr
->ifp
->vrf_id
, NULL
);
1091 if (r
->sock_rx
< 0 || r
->sock_tx
< 0) {
1092 const char *rxtx
= r
->sock_rx
< 0 ? "Rx" : "Tx";
1094 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1095 "Can't create VRRP %s socket",
1096 r
->vr
->vrid
, family2str(r
->family
), rxtx
);
1102 * Bind Tx socket to macvlan device - necessary for VRF support,
1103 * otherwise the kernel will select the vrf device
1105 if (r
->vr
->ifp
->vrf_id
!= VRF_DEFAULT
) {
1106 frr_with_privs (&vrrp_privs
) {
1107 ret
= setsockopt(r
->sock_tx
, SOL_SOCKET
,
1108 SO_BINDTODEVICE
, r
->mvl_ifp
->name
,
1109 strlen(r
->mvl_ifp
->name
));
1114 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1115 "Failed to bind Tx socket to macvlan device '%s'",
1116 r
->vr
->vrid
, family2str(r
->family
),
1122 /* Configure sockets */
1123 if (r
->family
== AF_INET
) {
1124 /* Set Tx socket to always Tx with TTL set to 255 */
1127 ret
= setsockopt(r
->sock_tx
, IPPROTO_IP
, IP_MULTICAST_TTL
, &ttl
,
1131 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1132 "Failed to set outgoing multicast TTL count to 255; RFC 5798 compliant implementations will drop our packets",
1133 r
->vr
->vrid
, family2str(r
->family
));
1136 /* Set Tx socket DSCP byte */
1137 setsockopt_ipv4_tos(r
->sock_tx
, IPTOS_PREC_INTERNETCONTROL
);
1139 /* Turn off multicast loop on Tx */
1140 setsockopt_ipv4_multicast_loop(r
->sock_tx
, 0);
1142 /* Bind Rx socket to exact interface */
1143 frr_with_privs(&vrrp_privs
) {
1144 ret
= setsockopt(r
->sock_rx
, SOL_SOCKET
,
1145 SO_BINDTODEVICE
, r
->vr
->ifp
->name
,
1146 strlen(r
->vr
->ifp
->name
));
1149 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1150 "Failed to bind Rx socket to %s: %s",
1151 r
->vr
->vrid
, family2str(r
->family
),
1152 r
->vr
->ifp
->name
, safe_strerror(errno
));
1156 DEBUGD(&vrrp_dbg_sock
,
1157 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1158 "Bound Rx socket to %s",
1159 r
->vr
->vrid
, family2str(r
->family
), r
->vr
->ifp
->name
);
1161 /* Bind Rx socket to v4 multicast address */
1162 struct sockaddr_in sa
= {0};
1164 sa
.sin_family
= AF_INET
;
1165 sa
.sin_addr
.s_addr
= htonl(VRRP_MCASTV4_GROUP
);
1166 if (bind(r
->sock_rx
, (struct sockaddr
*)&sa
, sizeof(sa
))) {
1168 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1169 "Failed to bind Rx socket to VRRP multicast group: %s",
1170 r
->vr
->vrid
, family2str(r
->family
),
1171 safe_strerror(errno
));
1175 DEBUGD(&vrrp_dbg_sock
,
1176 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1177 "Bound Rx socket to VRRP multicast group",
1178 r
->vr
->vrid
, family2str(r
->family
));
1180 /* Join Rx socket to VRRP IPv4 multicast group */
1181 assert(listhead(r
->vr
->ifp
->connected
));
1182 struct connected
*c
= listhead(r
->vr
->ifp
->connected
)->data
;
1183 struct in_addr v4
= c
->address
->u
.prefix4
;
1185 ret
= setsockopt_ipv4_multicast(r
->sock_rx
, IP_ADD_MEMBERSHIP
,
1186 v4
, htonl(VRRP_MCASTV4_GROUP
),
1187 r
->vr
->ifp
->ifindex
);
1189 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID
1190 "Failed to join VRRP %s multicast group",
1191 r
->vr
->vrid
, family2str(r
->family
));
1195 DEBUGD(&vrrp_dbg_sock
,
1196 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1197 "Joined VRRP multicast group",
1198 r
->vr
->vrid
, family2str(r
->family
));
1200 /* Set outgoing interface for advertisements */
1201 struct ip_mreqn mreqn
= {};
1203 mreqn
.imr_ifindex
= r
->mvl_ifp
->ifindex
;
1204 ret
= setsockopt(r
->sock_tx
, IPPROTO_IP
, IP_MULTICAST_IF
,
1205 (void *)&mreqn
, sizeof(mreqn
));
1208 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1209 "Could not set %s as outgoing multicast interface",
1210 r
->vr
->vrid
, family2str(r
->family
),
1215 DEBUGD(&vrrp_dbg_sock
,
1216 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1217 "Set %s as outgoing multicast interface",
1218 r
->vr
->vrid
, family2str(r
->family
), r
->mvl_ifp
->name
);
1220 /* Select and bind source address */
1221 if (vrrp_bind_to_primary_connected(r
) < 0) {
1226 } else if (r
->family
== AF_INET6
) {
1227 /* Always transmit IPv6 packets with hop limit set to 255 */
1228 ret
= setsockopt_ipv6_multicast_hops(r
->sock_tx
, 255);
1231 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1232 "Failed to set outgoing multicast hop count to 255; RFC 5798 compliant implementations will drop our packets",
1233 r
->vr
->vrid
, family2str(r
->family
));
1236 /* Set Tx socket DSCP byte */
1237 setsockopt_ipv6_tclass(r
->sock_tx
, IPTOS_PREC_INTERNETCONTROL
);
1239 /* Request hop limit delivery */
1240 setsockopt_ipv6_hoplimit(r
->sock_rx
, 1);
1242 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1243 "Failed to request IPv6 Hop Limit delivery",
1244 r
->vr
->vrid
, family2str(r
->family
));
1249 /* Turn off multicast loop on Tx */
1250 setsockopt_ipv6_multicast_loop(r
->sock_tx
, 0);
1252 /* Bind Rx socket to exact interface */
1253 frr_with_privs(&vrrp_privs
) {
1254 ret
= setsockopt(r
->sock_rx
, SOL_SOCKET
,
1255 SO_BINDTODEVICE
, r
->vr
->ifp
->name
,
1256 strlen(r
->vr
->ifp
->name
));
1259 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1260 "Failed to bind Rx socket to %s: %s",
1261 r
->vr
->vrid
, family2str(r
->family
),
1262 r
->vr
->ifp
->name
, safe_strerror(errno
));
1266 DEBUGD(&vrrp_dbg_sock
,
1267 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1268 "Bound Rx socket to %s",
1269 r
->vr
->vrid
, family2str(r
->family
), r
->vr
->ifp
->name
);
1271 /* Bind Rx socket to v6 multicast address */
1272 struct sockaddr_in6 sa
= {0};
1274 sa
.sin6_family
= AF_INET6
;
1275 inet_pton(AF_INET6
, VRRP_MCASTV6_GROUP_STR
, &sa
.sin6_addr
);
1276 if (bind(r
->sock_rx
, (struct sockaddr
*)&sa
, sizeof(sa
))) {
1278 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1279 "Failed to bind Rx socket to VRRP multicast group: %s",
1280 r
->vr
->vrid
, family2str(r
->family
),
1281 safe_strerror(errno
));
1285 DEBUGD(&vrrp_dbg_sock
,
1286 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1287 "Bound Rx socket to VRRP multicast group",
1288 r
->vr
->vrid
, family2str(r
->family
));
1290 /* Join VRRP IPv6 multicast group */
1291 struct ipv6_mreq mreq
;
1293 inet_pton(AF_INET6
, VRRP_MCASTV6_GROUP_STR
,
1294 &mreq
.ipv6mr_multiaddr
);
1295 mreq
.ipv6mr_interface
= r
->vr
->ifp
->ifindex
;
1296 ret
= setsockopt(r
->sock_rx
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
,
1297 &mreq
, sizeof(mreq
));
1299 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1300 "Failed to join VRRP multicast group",
1301 r
->vr
->vrid
, family2str(r
->family
));
1305 DEBUGD(&vrrp_dbg_sock
,
1306 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1307 "Joined VRRP multicast group",
1308 r
->vr
->vrid
, family2str(r
->family
));
1310 /* Set outgoing interface for advertisements */
1311 ret
= setsockopt(r
->sock_tx
, IPPROTO_IPV6
, IPV6_MULTICAST_IF
,
1312 &r
->mvl_ifp
->ifindex
, sizeof(ifindex_t
));
1315 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1316 "Could not set %s as outgoing multicast interface",
1317 r
->vr
->vrid
, family2str(r
->family
),
1322 DEBUGD(&vrrp_dbg_sock
,
1323 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1324 "Set %s as outgoing multicast interface",
1325 r
->vr
->vrid
, family2str(r
->family
), r
->mvl_ifp
->name
);
1331 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1332 "Failed to initialize VRRP router",
1333 r
->vr
->vrid
, family2str(r
->family
));
1334 if (r
->sock_rx
>= 0) {
1338 if (r
->sock_tx
>= 0) {
1349 /* State machine ----------------------------------------------------------- */
1351 DEFINE_HOOK(vrrp_change_state_hook
, (struct vrrp_router
*r
, int to
), (r
, to
));
1354 * Handle any necessary actions during state change to MASTER state.
1357 * VRRP Router to operate on
1359 static void vrrp_change_state_master(struct vrrp_router
*r
)
1361 /* Enable ND Router Advertisements */
1362 if (r
->family
== AF_INET6
)
1363 vrrp_zebra_radv_set(r
, true);
1365 /* Set protodown off */
1366 vrrp_zclient_send_interface_protodown(r
->mvl_ifp
, false);
1369 * If protodown is already off, we can send our stuff, otherwise we
1370 * have to delay until the interface is all the way up
1372 if (if_is_operative(r
->mvl_ifp
)) {
1373 vrrp_send_advertisement(r
);
1375 if (r
->family
== AF_INET
)
1376 vrrp_garp_send_all(r
);
1377 else if (r
->family
== AF_INET6
)
1378 vrrp_ndisc_una_send_all(r
);
1380 DEBUGD(&vrrp_dbg_proto
,
1381 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1382 "Delaying VRRP advertisement until interface is up",
1383 r
->vr
->vrid
, family2str(r
->family
));
1384 r
->advert_pending
= true;
1386 if (r
->family
== AF_INET
) {
1387 DEBUGD(&vrrp_dbg_proto
,
1388 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1389 "Delaying VRRP gratuitous ARPs until interface is up",
1390 r
->vr
->vrid
, family2str(r
->family
));
1391 r
->garp_pending
= true;
1392 } else if (r
->family
== AF_INET6
) {
1393 DEBUGD(&vrrp_dbg_proto
,
1394 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1395 "Delaying VRRP unsolicited neighbor advertisement until interface is up",
1396 r
->vr
->vrid
, family2str(r
->family
));
1397 r
->ndisc_pending
= true;
1403 * Handle any necessary actions during state change to BACKUP state.
1406 * Virtual Router to operate on
1408 static void vrrp_change_state_backup(struct vrrp_router
*r
)
1410 /* Disable ND Router Advertisements */
1411 if (r
->family
== AF_INET6
)
1412 vrrp_zebra_radv_set(r
, false);
1414 /* Disable Adver_Timer */
1415 THREAD_OFF(r
->t_adver_timer
);
1417 r
->advert_pending
= false;
1418 r
->garp_pending
= false;
1419 r
->ndisc_pending
= false;
1420 memset(&r
->src
, 0x00, sizeof(r
->src
));
1422 vrrp_zclient_send_interface_protodown(r
->mvl_ifp
, true);
1426 * Handle any necessary actions during state change to INITIALIZE state.
1428 * This is not called for initial startup, only when transitioning from MASTER
1432 * VRRP Router to operate on
1434 static void vrrp_change_state_initialize(struct vrrp_router
*r
)
1436 r
->master_adver_interval
= 0;
1437 vrrp_recalculate_timers(r
);
1439 r
->advert_pending
= false;
1440 r
->garp_pending
= false;
1441 r
->ndisc_pending
= false;
1443 /* Disable ND Router Advertisements */
1444 if (r
->family
== AF_INET6
&& r
->mvl_ifp
)
1445 vrrp_zebra_radv_set(r
, false);
1448 void (*const vrrp_change_state_handlers
[])(struct vrrp_router
*vr
) = {
1449 [VRRP_STATE_MASTER
] = vrrp_change_state_master
,
1450 [VRRP_STATE_BACKUP
] = vrrp_change_state_backup
,
1451 [VRRP_STATE_INITIALIZE
] = vrrp_change_state_initialize
,
1455 * Change Virtual Router FSM position. Handles transitional actions and calls
1456 * any subscribers to the state change hook.
1459 * Virtual Router for which to change state
1462 * State to change to
1464 static void vrrp_change_state(struct vrrp_router
*r
, int to
)
1466 if (r
->fsm
.state
== to
)
1469 /* Call our handlers, then any subscribers */
1470 vrrp_change_state_handlers
[to
](r
);
1471 hook_call(vrrp_change_state_hook
, r
, to
);
1472 zlog_info(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
"%s -> %s",
1473 r
->vr
->vrid
, family2str(r
->family
),
1474 vrrp_state_names
[r
->fsm
.state
], vrrp_state_names
[to
]);
1477 ++r
->stats
.trans_cnt
;
1481 * Called when Adver_Timer expires.
1483 static int vrrp_adver_timer_expire(struct thread
*thread
)
1485 struct vrrp_router
*r
= thread
->arg
;
1487 DEBUGD(&vrrp_dbg_proto
,
1488 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1489 "Adver_Timer expired",
1490 r
->vr
->vrid
, family2str(r
->family
));
1492 if (r
->fsm
.state
== VRRP_STATE_MASTER
) {
1493 /* Send an ADVERTISEMENT */
1494 vrrp_send_advertisement(r
);
1496 /* Reset the Adver_Timer to Advertisement_Interval */
1497 thread_add_timer_msec(master
, vrrp_adver_timer_expire
, r
,
1498 r
->vr
->advertisement_interval
* CS2MS
,
1501 zlog_err(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1502 "Adver_Timer expired in state '%s'; this is a bug",
1503 r
->vr
->vrid
, family2str(r
->family
),
1504 vrrp_state_names
[r
->fsm
.state
]);
1511 * Called when Master_Down_Timer expires.
1513 static int vrrp_master_down_timer_expire(struct thread
*thread
)
1515 struct vrrp_router
*r
= thread
->arg
;
1517 zlog_info(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1518 "Master_Down_Timer expired",
1519 r
->vr
->vrid
, family2str(r
->family
));
1521 thread_add_timer_msec(master
, vrrp_adver_timer_expire
, r
,
1522 r
->vr
->advertisement_interval
* CS2MS
,
1524 vrrp_change_state(r
, VRRP_STATE_MASTER
);
1530 * Event handler for Startup event.
1532 * Creates sockets, sends advertisements and ARP requests, starts timers,
1533 * and transitions the Virtual Router to either Master or Backup states.
1535 * This function will also initialize the program's global ARP subsystem if it
1536 * has not yet been initialized.
1539 * VRRP Router on which to apply Startup event
1542 * < 0 if the session socket could not be created, or the state is not
1546 static int vrrp_startup(struct vrrp_router
*r
)
1548 /* May only be called when the state is Initialize */
1549 if (r
->fsm
.state
!= VRRP_STATE_INITIALIZE
)
1552 /* Must have a valid macvlan interface available */
1553 if (r
->mvl_ifp
== NULL
&& !vrrp_attach_interface(r
)) {
1554 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1555 "No appropriate interface found",
1556 r
->vr
->vrid
, family2str(r
->family
));
1560 /* Initialize global gratuitous ARP socket if necessary */
1561 if (r
->family
== AF_INET
&& !vrrp_garp_is_init())
1563 if (r
->family
== AF_INET6
&& !vrrp_ndisc_is_init())
1567 if (r
->sock_rx
< 0 || r
->sock_tx
< 0) {
1568 int ret
= vrrp_socket(r
);
1570 if (ret
< 0 || r
->sock_tx
< 0 || r
->sock_rx
< 0)
1574 /* Schedule listener */
1575 thread_add_read(master
, vrrp_read
, r
, r
->sock_rx
, &r
->t_read
);
1577 /* Configure effective priority */
1578 assert(listhead(r
->addrs
));
1579 struct ipaddr
*primary
= (struct ipaddr
*)listhead(r
->addrs
)->data
;
1580 char ipbuf
[INET6_ADDRSTRLEN
];
1582 inet_ntop(r
->family
, &primary
->ip
.addr
, ipbuf
, sizeof(ipbuf
));
1584 if (r
->vr
->priority
== VRRP_PRIO_MASTER
1585 || vrrp_is_owner(r
->vr
->ifp
, primary
)) {
1586 r
->priority
= VRRP_PRIO_MASTER
;
1587 vrrp_recalculate_timers(r
);
1590 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1591 "%s has priority set to 255 or owns primary Virtual Router IP %s; electing self as Master",
1592 r
->vr
->vrid
, family2str(r
->family
), r
->vr
->ifp
->name
,
1596 if (r
->priority
== VRRP_PRIO_MASTER
) {
1597 thread_add_timer_msec(master
, vrrp_adver_timer_expire
, r
,
1598 r
->vr
->advertisement_interval
* CS2MS
,
1600 vrrp_change_state(r
, VRRP_STATE_MASTER
);
1602 r
->master_adver_interval
= r
->vr
->advertisement_interval
;
1603 vrrp_recalculate_timers(r
);
1604 thread_add_timer_msec(master
, vrrp_master_down_timer_expire
, r
,
1605 r
->master_down_interval
* CS2MS
,
1606 &r
->t_master_down_timer
);
1607 vrrp_change_state(r
, VRRP_STATE_BACKUP
);
1610 r
->is_active
= true;
1616 * Shuts down a Virtual Router and transitions it to Initialize.
1618 * This call must be idempotent; it is safe to call multiple times on the same
1621 static int vrrp_shutdown(struct vrrp_router
*r
)
1625 switch (r
->fsm
.state
) {
1626 case VRRP_STATE_MASTER
:
1627 /* Send an ADVERTISEMENT with Priority = 0 */
1628 saved_prio
= r
->priority
;
1630 vrrp_send_advertisement(r
);
1631 r
->priority
= saved_prio
;
1633 case VRRP_STATE_BACKUP
:
1635 case VRRP_STATE_INITIALIZE
:
1636 DEBUGD(&vrrp_dbg_proto
,
1637 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1638 "Received '%s' event in '%s' state; ignoring",
1639 r
->vr
->vrid
, family2str(r
->family
),
1640 vrrp_event_names
[VRRP_EVENT_SHUTDOWN
],
1641 vrrp_state_names
[VRRP_STATE_INITIALIZE
]);
1645 /* Cancel all timers */
1646 THREAD_OFF(r
->t_adver_timer
);
1647 THREAD_OFF(r
->t_master_down_timer
);
1648 THREAD_OFF(r
->t_read
);
1649 THREAD_OFF(r
->t_write
);
1651 /* Protodown macvlan */
1653 vrrp_zclient_send_interface_protodown(r
->mvl_ifp
, true);
1655 /* Throw away our source address */
1656 memset(&r
->src
, 0x00, sizeof(r
->src
));
1658 if (r
->sock_rx
> 0) {
1662 if (r
->sock_tx
> 0) {
1667 vrrp_change_state(r
, VRRP_STATE_INITIALIZE
);
1669 r
->is_active
= false;
1674 static int (*const vrrp_event_handlers
[])(struct vrrp_router
*r
) = {
1675 [VRRP_EVENT_STARTUP
] = vrrp_startup
,
1676 [VRRP_EVENT_SHUTDOWN
] = vrrp_shutdown
,
1680 * Spawn a VRRP FSM event on a VRRP Router.
1683 * VRRP Router on which to spawn event
1686 * The event to spawn
1692 int vrrp_event(struct vrrp_router
*r
, int event
)
1694 zlog_info(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
"'%s' event",
1695 r
->vr
->vrid
, family2str(r
->family
), vrrp_event_names
[event
]);
1696 return vrrp_event_handlers
[event
](r
);
1700 /* Autoconfig -------------------------------------------------------------- */
1703 * Set the configured addresses for this VRRP instance to exactly the addresses
1704 * present on its macvlan subinterface(s).
1707 * VRRP router to act on
1709 static void vrrp_autoconfig_autoaddrupdate(struct vrrp_router
*r
)
1711 struct listnode
*ln
;
1712 struct connected
*c
= NULL
;
1718 DEBUGD(&vrrp_dbg_auto
,
1719 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1720 "Setting Virtual IP list to match IPv4 addresses on %s",
1721 r
->vr
->vrid
, family2str(r
->family
), r
->mvl_ifp
->name
);
1722 for (ALL_LIST_ELEMENTS_RO(r
->mvl_ifp
->connected
, ln
, c
)) {
1723 is_v6_ll
= (c
->address
->family
== AF_INET6
1724 && IN6_IS_ADDR_LINKLOCAL(&c
->address
->u
.prefix6
));
1725 if (c
->address
->family
== r
->family
&& !is_v6_ll
) {
1726 DEBUGD(&vrrp_dbg_auto
,
1727 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1729 r
->vr
->vrid
, family2str(r
->family
), c
->address
);
1730 if (r
->family
== AF_INET
)
1731 vrrp_add_ipv4(r
->vr
, c
->address
->u
.prefix4
);
1732 else if (r
->vr
->version
== 3)
1733 vrrp_add_ipv6(r
->vr
, c
->address
->u
.prefix6
);
1737 vrrp_check_start(r
->vr
);
1739 if (r
->addrs
->count
== 0 && r
->fsm
.state
!= VRRP_STATE_INITIALIZE
) {
1740 DEBUGD(&vrrp_dbg_auto
,
1741 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1742 "Virtual IP list is empty; shutting down",
1743 r
->vr
->vrid
, family2str(r
->family
));
1744 vrrp_event(r
, VRRP_EVENT_SHUTDOWN
);
1748 static struct vrrp_vrouter
*
1749 vrrp_autoconfig_autocreate(struct interface
*mvl_ifp
)
1751 struct interface
*p
;
1752 struct vrrp_vrouter
*vr
;
1754 p
= if_lookup_by_index(mvl_ifp
->link_ifindex
, mvl_ifp
->vrf_id
);
1759 uint8_t vrid
= mvl_ifp
->hw_addr
[5];
1760 uint8_t fam
= mvl_ifp
->hw_addr
[4];
1762 DEBUGD(&vrrp_dbg_auto
,
1763 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1764 "Autoconfiguring VRRP on %s",
1765 vrid
, family2str(fam
), p
->name
);
1767 vr
= vrrp_vrouter_create(p
, vrid
, vrrp_autoconfig_version
);
1770 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1771 "Failed to autoconfigure VRRP on %s",
1772 vrid
, family2str(fam
), p
->name
);
1776 vr
->autoconf
= true;
1779 * If these interfaces are protodown on, we need to un-protodown them
1780 * in order to get Zebra to send us their addresses so we can
1781 * autoconfigure them.
1783 if (vr
->v4
->mvl_ifp
)
1784 vrrp_zclient_send_interface_protodown(vr
->v4
->mvl_ifp
, false);
1785 if (vr
->v6
->mvl_ifp
)
1786 vrrp_zclient_send_interface_protodown(vr
->v6
->mvl_ifp
, false);
1788 /* If they're not, we can go ahead and add the addresses we have */
1789 vrrp_autoconfig_autoaddrupdate(vr
->v4
);
1790 vrrp_autoconfig_autoaddrupdate(vr
->v6
);
1796 * Callback to notify autoconfig of interface add.
1798 * If the interface is a VRRP-compatible device, and there is no existing VRRP
1799 * router running on it, one is created. All addresses on the interface are
1800 * added to the router.
1803 * Interface to operate on
1809 static int vrrp_autoconfig_if_add(struct interface
*ifp
)
1811 bool created
= false;
1812 struct vrrp_vrouter
*vr
;
1814 if (!vrrp_autoconfig_is_on
)
1817 if (!ifp
|| !ifp
->link_ifindex
|| !vrrp_ifp_has_vrrp_mac(ifp
))
1820 vr
= vrrp_lookup_by_if_mvl(ifp
);
1823 vr
= vrrp_autoconfig_autocreate(ifp
);
1827 if (!vr
|| !vr
->autoconf
)
1832 * We didn't create it, but it has already been autoconfigured.
1833 * Try to attach this interface to the existing instance.
1835 if (!vr
->v4
->mvl_ifp
) {
1836 vrrp_attach_interface(vr
->v4
);
1837 /* If we just attached it, make sure it's turned on */
1838 if (vr
->v4
->mvl_ifp
) {
1839 vrrp_zclient_send_interface_protodown(
1840 vr
->v4
->mvl_ifp
, false);
1842 * If it's already up, we can go ahead and add
1843 * the addresses we have
1845 vrrp_autoconfig_autoaddrupdate(vr
->v4
);
1848 if (!vr
->v6
->mvl_ifp
) {
1849 vrrp_attach_interface(vr
->v6
);
1850 /* If we just attached it, make sure it's turned on */
1851 if (vr
->v6
->mvl_ifp
) {
1852 vrrp_zclient_send_interface_protodown(
1853 vr
->v6
->mvl_ifp
, false);
1855 * If it's already up, we can go ahead and add
1856 * the addresses we have
1858 vrrp_autoconfig_autoaddrupdate(vr
->v6
);
1867 * Callback to notify autoconfig of interface delete.
1869 * If the interface is a VRRP-compatible device, and a VRRP router is running
1870 * on it, and that VRRP router was automatically configured, it will be
1871 * deleted. If that was the last router for the corresponding VRID (i.e., if
1872 * this interface was a v4 VRRP interface and no v6 router is configured for
1873 * the same VRID) then the entire virtual router is deleted.
1876 * Interface to operate on
1882 static int vrrp_autoconfig_if_del(struct interface
*ifp
)
1884 if (!vrrp_autoconfig_is_on
)
1887 struct vrrp_vrouter
*vr
;
1888 struct listnode
*ln
;
1891 vrs
= vrrp_lookup_by_if_any(ifp
);
1893 for (ALL_LIST_ELEMENTS_RO(vrs
, ln
, vr
))
1895 && (!vr
->ifp
|| (!vr
->v4
->mvl_ifp
&& !vr
->v6
->mvl_ifp
))) {
1896 DEBUGD(&vrrp_dbg_auto
,
1897 VRRP_LOGPFX VRRP_LOGPFX_VRID
1898 "All VRRP interfaces for instance deleted; destroying autoconfigured VRRP router",
1900 vrrp_vrouter_destroy(vr
);
1909 * Callback to notify autoconfig of interface up.
1911 * Creates VRRP instance on interface if it does not exist. Otherwise does
1915 * Interface to operate on
1921 static int vrrp_autoconfig_if_up(struct interface
*ifp
)
1923 if (!vrrp_autoconfig_is_on
)
1926 struct vrrp_vrouter
*vr
= vrrp_lookup_by_if_mvl(ifp
);
1928 if (vr
&& !vr
->autoconf
)
1932 vrrp_autoconfig_if_add(ifp
);
1940 * Callback to notify autoconfig of interface down.
1942 * Does nothing. An interface down event is accompanied by address deletion
1943 * events for all the addresses on the interface; if an autoconfigured VRRP
1944 * router exists on this interface, then it will have all its addresses deleted
1945 * and end up in Initialize.
1948 * Interface to operate on
1954 static int vrrp_autoconfig_if_down(struct interface
*ifp
)
1956 if (!vrrp_autoconfig_is_on
)
1963 * Callback to notify autoconfig of a new interface address.
1965 * If a VRRP router exists on this interface, its address list is updated to
1966 * match the new address list. If no addresses remain, a Shutdown event is
1967 * issued to the VRRP router.
1970 * Interface to operate on
1977 static int vrrp_autoconfig_if_address_add(struct interface
*ifp
)
1979 if (!vrrp_autoconfig_is_on
)
1982 struct vrrp_vrouter
*vr
= vrrp_lookup_by_if_mvl(ifp
);
1984 if (vr
&& vr
->autoconf
) {
1985 if (vr
->v4
->mvl_ifp
== ifp
)
1986 vrrp_autoconfig_autoaddrupdate(vr
->v4
);
1987 else if (vr
->v6
->mvl_ifp
== ifp
)
1988 vrrp_autoconfig_autoaddrupdate(vr
->v6
);
1995 * Callback to notify autoconfig of a removed interface address.
1997 * If a VRRP router exists on this interface, its address list is updated to
1998 * match the new address list. If no addresses remain, a Shutdown event is
1999 * issued to the VRRP router.
2002 * Interface to operate on
2009 static int vrrp_autoconfig_if_address_del(struct interface
*ifp
)
2011 if (!vrrp_autoconfig_is_on
)
2014 struct vrrp_vrouter
*vr
= vrrp_lookup_by_if_mvl(ifp
);
2016 if (vr
&& vr
->autoconf
) {
2017 if (vr
->v4
->mvl_ifp
== ifp
)
2018 vrrp_autoconfig_autoaddrupdate(vr
->v4
);
2019 else if (vr
->v6
->mvl_ifp
== ifp
)
2020 vrrp_autoconfig_autoaddrupdate(vr
->v6
);
2026 int vrrp_autoconfig(void)
2028 if (!vrrp_autoconfig_is_on
)
2032 struct interface
*ifp
;
2034 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2035 FOR_ALL_INTERFACES (vrf
, ifp
)
2036 vrrp_autoconfig_if_add(ifp
);
2042 void vrrp_autoconfig_on(int version
)
2044 vrrp_autoconfig_is_on
= true;
2045 vrrp_autoconfig_version
= version
;
2050 void vrrp_autoconfig_off(void)
2052 vrrp_autoconfig_is_on
= false;
2054 struct list
*ll
= hash_to_list(vrrp_vrouters_hash
);
2056 struct listnode
*ln
;
2057 struct vrrp_vrouter
*vr
;
2059 for (ALL_LIST_ELEMENTS_RO(ll
, ln
, vr
))
2061 vrrp_vrouter_destroy(vr
);
2066 /* Interface tracking ------------------------------------------------------ */
2069 * Bind any pending interfaces.
2072 * macvlan interface that some VRRP instances might want to bind to
2074 static void vrrp_bind_pending(struct interface
*mvl_ifp
)
2076 struct vrrp_vrouter
*vr
;
2078 DEBUGD(&vrrp_dbg_zebra
,
2080 "Searching for instances that could use interface %s",
2083 vr
= vrrp_lookup_by_if_mvl(mvl_ifp
);
2086 DEBUGD(&vrrp_dbg_zebra
,
2087 VRRP_LOGPFX VRRP_LOGPFX_VRID
2088 "<-- This instance can probably use interface %s",
2089 vr
->vrid
, mvl_ifp
->name
);
2091 if (mvl_ifp
->hw_addr
[4] == 0x01 && !vr
->v4
->mvl_ifp
)
2092 vrrp_attach_interface(vr
->v4
);
2093 else if (mvl_ifp
->hw_addr
[4] == 0x02 && !vr
->v6
->mvl_ifp
)
2094 vrrp_attach_interface(vr
->v6
);
2098 void vrrp_if_up(struct interface
*ifp
)
2100 struct vrrp_vrouter
*vr
;
2101 struct listnode
*ln
;
2104 vrrp_bind_pending(ifp
);
2106 vrs
= vrrp_lookup_by_if_any(ifp
);
2108 for (ALL_LIST_ELEMENTS_RO(vrs
, ln
, vr
)) {
2109 vrrp_check_start(vr
);
2111 if (!if_is_operative(ifp
))
2115 * Handle the situation in which we performed a state
2116 * transition on this VRRP router but needed to wait for the
2117 * macvlan interface to come up to perform some actions
2119 if (ifp
== vr
->v4
->mvl_ifp
) {
2120 if (vr
->v4
->advert_pending
) {
2121 DEBUGD(&vrrp_dbg_proto
,
2122 VRRP_LOGPFX VRRP_LOGPFX_VRID
2124 "Interface up; sending pending advertisement",
2125 vr
->vrid
, family2str(vr
->v4
->family
));
2126 vrrp_send_advertisement(vr
->v4
);
2127 vr
->v4
->advert_pending
= false;
2129 if (vr
->v4
->garp_pending
) {
2130 DEBUGD(&vrrp_dbg_proto
,
2131 VRRP_LOGPFX VRRP_LOGPFX_VRID
2133 "Interface up; sending pending gratuitous ARP",
2134 vr
->vrid
, family2str(vr
->v4
->family
));
2135 vrrp_garp_send_all(vr
->v4
);
2136 vr
->v4
->garp_pending
= false;
2139 if (ifp
== vr
->v6
->mvl_ifp
) {
2140 if (vr
->v6
->advert_pending
) {
2141 DEBUGD(&vrrp_dbg_proto
,
2142 VRRP_LOGPFX VRRP_LOGPFX_VRID
2144 "Interface up; sending pending advertisement",
2145 vr
->vrid
, family2str(vr
->v6
->family
));
2146 vrrp_send_advertisement(vr
->v6
);
2147 vr
->v6
->advert_pending
= false;
2149 if (vr
->v6
->ndisc_pending
) {
2150 DEBUGD(&vrrp_dbg_proto
,
2151 VRRP_LOGPFX VRRP_LOGPFX_VRID
2153 "Interface up; sending pending Unsolicited Neighbor Advertisement",
2154 vr
->vrid
, family2str(vr
->v6
->family
));
2155 vrrp_ndisc_una_send_all(vr
->v6
);
2156 vr
->v6
->ndisc_pending
= false;
2163 vrrp_autoconfig_if_up(ifp
);
2166 void vrrp_if_down(struct interface
*ifp
)
2168 struct vrrp_vrouter
*vr
;
2169 struct listnode
*ln
;
2172 vrrp_bind_pending(ifp
);
2174 vrs
= vrrp_lookup_by_if_any(ifp
);
2176 for (ALL_LIST_ELEMENTS_RO(vrs
, ln
, vr
)) {
2177 vrrp_check_start(vr
);
2179 if (vr
->ifp
== ifp
|| vr
->v4
->mvl_ifp
== ifp
2180 || vr
->v6
->mvl_ifp
== ifp
) {
2181 DEBUGD(&vrrp_dbg_auto
,
2182 VRRP_LOGPFX VRRP_LOGPFX_VRID
"Interface %s down",
2183 vr
->vrid
, ifp
->name
);
2189 vrrp_autoconfig_if_down(ifp
);
2192 void vrrp_if_add(struct interface
*ifp
)
2194 vrrp_bind_pending(ifp
);
2197 if (CHECK_FLAG(ifp
->flags
, IFF_UP
))
2200 vrrp_autoconfig_if_add(ifp
);
2203 void vrrp_if_del(struct interface
*ifp
)
2205 struct listnode
*ln
;
2206 struct vrrp_vrouter
*vr
;
2211 * You think we'd be able use vrrp_lookup_by_if_any to find interfaces?
2212 * Nah. FRR's interface management is insane. There are no ordering
2213 * guarantees about what interfaces are deleted when. Maybe this is a
2214 * macvlan and its parent was already deleted, in which case its
2215 * ifindex is now IFINDEX_INTERNAL, so ifp->link_ifindex - while still
2216 * valid - doesn't match any interface on the system, meaning we can't
2217 * use any of the vrrp_lookup* functions since they rely on finding the
2218 * base interface of what they're given by following link_ifindex.
2220 * Since we need to actually NULL out pointers in this function to
2221 * avoid a UAF - since the caller will (might) free ifp after we return
2222 * - we need to look up based on pointers.
2224 struct list
*vrs
= hash_to_list(vrrp_vrouters_hash
);
2226 for (ALL_LIST_ELEMENTS_RO(vrs
, ln
, vr
)) {
2227 if (ifp
== vr
->ifp
) {
2228 vrrp_event(vr
->v4
, VRRP_EVENT_SHUTDOWN
);
2229 vrrp_event(vr
->v6
, VRRP_EVENT_SHUTDOWN
);
2231 * Stands to reason if the base was deleted, so were
2232 * (or will be) its children
2234 vr
->v4
->mvl_ifp
= NULL
;
2235 vr
->v6
->mvl_ifp
= NULL
;
2237 * We shouldn't need to lose the reference if it's the
2238 * primary interface, because that was configured
2239 * explicitly in our config, and thus will be kept as a
2240 * stub; to avoid stupid bugs, double check that
2242 assert(ifp
->configured
);
2243 } else if (ifp
== vr
->v4
->mvl_ifp
) {
2244 vrrp_event(vr
->v4
, VRRP_EVENT_SHUTDOWN
);
2246 * If this is a macvlan, then it wasn't explicitly
2247 * configured and will be deleted when we return from
2248 * this function, so we need to lose the reference
2250 vr
->v4
->mvl_ifp
= NULL
;
2251 } else if (ifp
== vr
->v6
->mvl_ifp
) {
2252 vrrp_event(vr
->v6
, VRRP_EVENT_SHUTDOWN
);
2254 * If this is a macvlan, then it wasn't explicitly
2255 * configured and will be deleted when we return from
2256 * this function, so we need to lose the reference
2258 vr
->v6
->mvl_ifp
= NULL
;
2264 vrrp_autoconfig_if_del(ifp
);
2267 void vrrp_if_address_add(struct interface
*ifp
)
2269 struct vrrp_vrouter
*vr
;
2270 struct listnode
*ln
;
2274 * We have to do a wide search here, because we need to know when a v6
2275 * macvlan device gets a new address. This is because the macvlan link
2276 * local is used as the source address for v6 advertisements, and hence
2277 * "do I have a link local" constitutes an activation condition for v6
2280 vrs
= vrrp_lookup_by_if_any(ifp
);
2282 for (ALL_LIST_ELEMENTS_RO(vrs
, ln
, vr
))
2283 vrrp_check_start(vr
);
2287 vrrp_autoconfig_if_address_add(ifp
);
2290 void vrrp_if_address_del(struct interface
*ifp
)
2293 * Zebra is stupid and sends us address deletion notifications
2294 * when any of the following condition sets are met:
2296 * - if_is_operative && address deleted
2297 * - if_is_operative -> !if_is_operative
2299 * Note that the second one is nonsense, because Zebra behaves as
2300 * though an interface going down means all the addresses on that
2301 * interface got deleted. Which is a problem for autoconfig because all
2302 * the addresses on an interface going away means the VRRP session goes
2303 * to Initialize. However interfaces go down whenever we transition to
2304 * Backup, so this effectively means that for autoconfigured instances
2305 * we actually end up in Initialize whenever we try to go into Backup.
2307 * Also, Zebra does NOT send us notifications when:
2308 * - !if_is_operative && address deleted
2310 * Which means if we're in backup and an address is deleted out from
2311 * under us, we won't even know.
2313 * The only solution here is to only resynchronize our address list
2316 * - An interfaces comes up
2317 * - An interface address is added
2318 * - An interface address is deleted AND the interface is up
2320 * Even though this is only a problem with autoconfig at the moment I'm
2321 * papering over Zebra's braindead semantics here. Every piece of code
2322 * in this function should be protected by a check that the interface
2325 if (if_is_operative(ifp
))
2326 vrrp_autoconfig_if_address_del(ifp
);
2329 /* Other ------------------------------------------------------------------- */
2331 int vrrp_config_write_global(struct vty
*vty
)
2333 unsigned int writes
= 0;
2335 if (vrrp_autoconfig_is_on
&& ++writes
)
2336 vty_out(vty
, "vrrp autoconfigure%s\n",
2337 vrrp_autoconfig_version
== 2 ? " version 2" : "");
2339 /* FIXME: needs to be udpated for full YANG conversion. */
2340 if (vd
.priority
!= VRRP_DEFAULT_PRIORITY
&& ++writes
)
2341 vty_out(vty
, "vrrp default priority %hhu\n", vd
.priority
);
2343 if (vd
.advertisement_interval
!= VRRP_DEFAULT_ADVINT
&& ++writes
)
2345 "vrrp default advertisement-interval %u\n",
2346 vd
.advertisement_interval
* CS2MS
);
2348 if (vd
.preempt_mode
!= VRRP_DEFAULT_PREEMPT
&& ++writes
)
2349 vty_out(vty
, "%svrrp default preempt\n",
2350 !vd
.preempt_mode
? "no " : "");
2352 if (vd
.accept_mode
!= VRRP_DEFAULT_ACCEPT
&& ++writes
)
2353 vty_out(vty
, "%svrrp default accept\n",
2354 !vd
.accept_mode
? "no " : "");
2356 if (vd
.shutdown
!= VRRP_DEFAULT_SHUTDOWN
&& ++writes
)
2357 vty_out(vty
, "%svrrp default shutdown\n",
2358 !vd
.shutdown
? "no " : "");
2363 static unsigned int vrrp_hash_key(const void *arg
)
2365 const struct vrrp_vrouter
*vr
= arg
;
2366 char key
[IFNAMSIZ
+ 64];
2368 snprintf(key
, sizeof(key
), "%s@%u", vr
->ifp
->name
, vr
->vrid
);
2370 return string_hash_make(key
);
2373 static bool vrrp_hash_cmp(const void *arg1
, const void *arg2
)
2375 const struct vrrp_vrouter
*vr1
= arg1
;
2376 const struct vrrp_vrouter
*vr2
= arg2
;
2378 if (vr1
->ifp
!= vr2
->ifp
)
2380 if (vr1
->vrid
!= vr2
->vrid
)
2386 void vrrp_init(void)
2388 /* Set default defaults */
2389 vd
.version
= yang_get_default_uint8("%s/version", VRRP_XPATH_FULL
);
2390 vd
.priority
= yang_get_default_uint8("%s/priority", VRRP_XPATH_FULL
);
2391 vd
.advertisement_interval
= yang_get_default_uint16(
2392 "%s/advertisement-interval", VRRP_XPATH_FULL
);
2393 vd
.preempt_mode
= yang_get_default_bool("%s/preempt", VRRP_XPATH_FULL
);
2395 yang_get_default_bool("%s/accept-mode", VRRP_XPATH_FULL
);
2396 vd
.shutdown
= VRRP_DEFAULT_SHUTDOWN
;
2398 vrrp_autoconfig_version
= 3;
2399 vrrp_vrouters_hash
= hash_create(&vrrp_hash_key
, vrrp_hash_cmp
,
2400 "VRRP virtual router hash");
2401 vrf_init(NULL
, NULL
, NULL
, NULL
, NULL
);
2404 void vrrp_fini(void)
2406 /* Destroy all instances */
2407 struct list
*vrs
= hash_to_list(vrrp_vrouters_hash
);
2409 struct listnode
*ln
;
2410 struct vrrp_vrouter
*vr
;
2412 for (ALL_LIST_ELEMENTS_RO(vrs
, ln
, vr
))
2413 vrrp_vrouter_destroy(vr
);
2417 hash_clean(vrrp_vrouters_hash
, NULL
);
2418 hash_free(vrrp_vrouters_hash
);