summaryrefslogtreecommitdiffstats
path: root/vrrpd/vrrp.c
diff options
context:
space:
mode:
authorQuentin Young <qlyoung@cumulusnetworks.com>2019-03-04 19:46:08 +0100
committerQuentin Young <qlyoung@cumulusnetworks.com>2019-05-17 02:27:08 +0200
commitd60b2ffdfad204b675f642e9b712034e8dcef432 (patch)
treea6c847794f9c060d1662b9424b39fce87c90b0c0 /vrrpd/vrrp.c
parentvrrpd: allow user to set priority = 255 (diff)
downloadfrr-d60b2ffdfad204b675f642e9b712034e8dcef432.tar.xz
frr-d60b2ffdfad204b675f642e9b712034e8dcef432.zip
vrrpd: delay sending adverts/garp/una for iface up
When transitioning to Master from Backup, wait until Zebra sets the macvlan device to protodown off before transmitting advertisements, gratuitous ARPs, or Unsolicited Neighbor Advertisements. Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
Diffstat (limited to 'vrrpd/vrrp.c')
-rw-r--r--vrrpd/vrrp.c82
1 files changed, 74 insertions, 8 deletions
diff --git a/vrrpd/vrrp.c b/vrrpd/vrrp.c
index fc0a57b71..070bb9cc7 100644
--- a/vrrpd/vrrp.c
+++ b/vrrpd/vrrp.c
@@ -553,10 +553,12 @@ static void vrrp_router_destroy(struct vrrp_router *r)
if (r->is_active)
vrrp_event(r, VRRP_EVENT_SHUTDOWN);
- if (r->sock_rx >= 0)
+ if (r->sock_rx >= 0) {
close(r->sock_rx);
- if (r->sock_tx >= 0)
+ }
+ if (r->sock_tx >= 0) {
close(r->sock_tx);
+ }
/* FIXME: also delete list elements */
list_delete(&r->addrs);
@@ -1276,6 +1278,11 @@ static void vrrp_change_state_backup(struct vrrp_router *r)
/* Disable Adver_Timer */
THREAD_OFF(r->t_adver_timer);
+ /* This should not be necessary, but just in case */
+ r->advert_pending = false;
+ r->garp_pending = false;
+ r->ndisc_pending = false;
+
vrrp_zclient_send_interface_protodown(r->mvl_ifp, true);
}
@@ -1294,6 +1301,11 @@ static void vrrp_change_state_initialize(struct vrrp_router *r)
r->master_adver_interval = 0;
vrrp_recalculate_timers(r);
+ /* This should not be necessary, but just in case */
+ r->advert_pending = false;
+ r->garp_pending = false;
+ r->ndisc_pending = false;
+
/* Disable ND Router Advertisements */
if (r->family == AF_INET6)
vrrp_zebra_radv_set(r, false);
@@ -1367,16 +1379,23 @@ static int vrrp_master_down_timer_expire(struct thread *thread)
zlog_info(VRRP_LOGPFX VRRP_LOGPFX_VRID "Master_Down_Timer expired",
r->vr->vrid);
- vrrp_send_advertisement(r);
- if (r->family == AF_INET)
- vrrp_garp_send_all(r);
- if (r->family == AF_INET6)
- vrrp_ndisc_una_send_all(r);
thread_add_timer_msec(master, vrrp_adver_timer_expire, r,
r->vr->advertisement_interval * 10,
&r->t_adver_timer);
vrrp_change_state(r, VRRP_STATE_MASTER);
+ /*
+ * Since this implemention uses protodown to implement backup status,
+ * we have to wait for the interface to come up before we can send our
+ * initial advert and garp/ndisc packets. This will be handled in
+ * vrrp_if_up().
+ */
+ r->advert_pending = true;
+ if (r->family == AF_INET)
+ r->garp_pending = true;
+ if (r->family == AF_INET6)
+ r->ndisc_pending = true;
+
return 0;
}
@@ -1512,6 +1531,10 @@ static int vrrp_shutdown(struct vrrp_router *r)
r->sock_tx = -1;
}
+ r->advert_pending = false;
+ r->garp_pending = false;
+ r->ndisc_pending = false;
+
vrrp_change_state(r, VRRP_STATE_INITIALIZE);
r->is_active = false;
@@ -1942,9 +1965,52 @@ void vrrp_if_up(struct interface *ifp)
vrs = vrrp_lookup_by_if_any(ifp);
- for (ALL_LIST_ELEMENTS_RO(vrs, ln, vr))
+ for (ALL_LIST_ELEMENTS_RO(vrs, ln, vr)) {
vrrp_check_start(vr);
+ /*
+ * Handle the situation in which we performed a state
+ * transition on this VRRP router but needed to wait for the
+ * macvlan interface to come up to perform some actions
+ */
+ if (ifp == vr->v4->mvl_ifp) {
+ if (vr->v4->advert_pending) {
+ DEBUGD(&vrrp_dbg_proto,
+ VRRP_LOGPFX VRRP_LOGPFX_VRID
+ "Interface up; sending pending advertisement",
+ vr->vrid);
+ vrrp_send_advertisement(vr->v4);
+ vr->v4->advert_pending = false;
+ }
+ if (vr->v4->garp_pending) {
+ DEBUGD(&vrrp_dbg_proto,
+ VRRP_LOGPFX VRRP_LOGPFX_VRID
+ "Interface up; sending pending gratuitous ARP",
+ vr->vrid);
+ vrrp_garp_send_all(vr->v4);
+ vr->v4->garp_pending = false;
+ }
+ }
+ if (ifp == vr->v6->mvl_ifp) {
+ if (vr->v6->advert_pending) {
+ DEBUGD(&vrrp_dbg_proto,
+ VRRP_LOGPFX VRRP_LOGPFX_VRID
+ "Interface up; sending pending advertisement",
+ vr->vrid);
+ vrrp_send_advertisement(vr->v6);
+ vr->v6->advert_pending = false;
+ }
+ if (vr->v6->ndisc_pending) {
+ DEBUGD(&vrrp_dbg_proto,
+ VRRP_LOGPFX VRRP_LOGPFX_VRID
+ "Interface up; sending pending Unsolicited Neighbor Advertisement",
+ vr->vrid);
+ vrrp_ndisc_una_send_all(vr->v6);
+ vr->v6->ndisc_pending = false;
+ }
+ }
+ }
+
list_delete(&vrs);
vrrp_autoconfig_if_up(ifp);