From 2270f6699514012f8111600cc3dd0c50295c427a Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 16 Nov 2010 19:05:26 +0100 Subject: vrrp: send continuous ARPs during the GARP delay (V2) If the link between the master and the backup is cut for too short a time, only one single GARP is sent by both sides at the same time, often causing some machines to only keep the backup one due to network delays. Now we make the master send GARPs for as long as the vrrp_garp_master_delay is defined. That way we ensure that every host gets a valid ARP update in time. Also, this update to the patch ensures that we always register the ARP thread only once. Earlier versions could have it called twice, resulting in halving the ARP period. --- keepalived/include/vrrp.h | 1 + keepalived/include/vrrp_scheduler.h | 1 + keepalived/vrrp/vrrp.c | 12 +++++++++++- keepalived/vrrp/vrrp_scheduler.c | 18 ++++++++++++++---- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/keepalived/include/vrrp.h b/keepalived/include/vrrp.h index 0542f5a..fbe571b 100644 --- a/keepalived/include/vrrp.h +++ b/keepalived/include/vrrp.h @@ -99,6 +99,7 @@ typedef struct _vrrp_rt { * => eth0 for example. */ int garp_delay; /* Delay to launch gratuitous ARP */ + int garp_left; /* number of ARPs left to send */ int vrid; /* virtual id. from 1(!) to 255 */ int base_priority; /* configured priority value */ int effective_priority; /* effective priority value */ diff --git a/keepalived/include/vrrp_scheduler.h b/keepalived/include/vrrp_scheduler.h index ca7071e..db49e59 100644 --- a/keepalived/include/vrrp_scheduler.h +++ b/keepalived/include/vrrp_scheduler.h @@ -61,5 +61,6 @@ do { \ extern void vrrp_dispatcher_release(vrrp_conf_data * conf_data_obj); extern int vrrp_dispatcher_init(thread * thread_obj); extern int vrrp_read_dispatcher_thread(thread * thread_obj); +extern int vrrp_gratuitous_arp_thread(thread * thread_obj); #endif diff --git a/keepalived/vrrp/vrrp.c b/keepalived/vrrp/vrrp.c index 73fa36a..67860ff 100644 --- a/keepalived/vrrp/vrrp.c +++ b/keepalived/vrrp/vrrp.c @@ -577,8 +577,10 @@ vrrp_send_gratuitous_arp(vrrp_rt * vrrp) element e; /* Only send gratuitous ARP if VIP are set */ - if (!VRRP_VIP_ISSET(vrrp)) + if (!VRRP_VIP_ISSET(vrrp)) { + vrrp->garp_left = 0; return; + } /* send gratuitous arp for each virtual ip */ for (j = 0; j < 5; j++) { @@ -626,6 +628,10 @@ vrrp_state_become_master(vrrp_rt * vrrp) /* remotes arp tables update */ vrrp_send_gratuitous_arp(vrrp); + if (!vrrp->garp_left) { + vrrp->garp_left = (vrrp->garp_delay) ? vrrp->garp_delay : VRRP_GARP_DELAY; + thread_add_timer(master, vrrp_gratuitous_arp_thread, vrrp, 1*TIMER_HZ); + } /* Check if notify is needed */ notify_instance_exec(vrrp, VRRP_STATE_MAST); @@ -824,6 +830,10 @@ vrrp_state_master_rx(vrrp_rt * vrrp, char *buf, int buflen) } vrrp_send_adv(vrrp, vrrp->effective_priority); vrrp_send_gratuitous_arp(vrrp); + if (!vrrp->garp_left) { + vrrp->garp_left = (vrrp->garp_delay) ? vrrp->garp_delay : VRRP_GARP_DELAY; + thread_add_timer(master, vrrp_gratuitous_arp_thread, vrrp, 1*TIMER_HZ); + } return 0; } else if (hd->priority == 0) { vrrp_send_adv(vrrp, vrrp->effective_priority); diff --git a/keepalived/vrrp/vrrp_scheduler.c b/keepalived/vrrp/vrrp_scheduler.c index a1d29b7..b0ee2c3 100644 --- a/keepalived/vrrp/vrrp_scheduler.c +++ b/keepalived/vrrp/vrrp_scheduler.c @@ -673,8 +673,18 @@ vrrp_gratuitous_arp_thread(thread * thread_obj) vrrp_rt *vrrp = THREAD_ARG(thread_obj); /* Simply broadcast the gratuitous ARP */ + if (vrrp->garp_left <= 0) + return 0; + vrrp_send_gratuitous_arp(vrrp); + vrrp->garp_left -= 1*TIMER_HZ; + if (vrrp->garp_left <= 0) { + vrrp->garp_left = 0; + return 0; + } + + thread_add_timer(master, vrrp_gratuitous_arp_thread, vrrp, 1*TIMER_HZ); return 0; } @@ -751,10 +761,10 @@ vrrp_master(vrrp_rt * vrrp) * register a gratuitous arp thread delayed to 5 secs. */ if (vrrp_state_master_tx(vrrp, 0)) { - thread_add_timer(master, vrrp_gratuitous_arp_thread, - vrrp, - (vrrp->garp_delay) ? - vrrp->garp_delay : VRRP_GARP_DELAY); + if (!vrrp->garp_left) { + vrrp->garp_left = (vrrp->garp_delay) ? vrrp->garp_delay : VRRP_GARP_DELAY; + thread_add_timer(master, vrrp_gratuitous_arp_thread, vrrp, 1*TIMER_HZ); + } vrrp_smtp_notifier(vrrp); } } -- 1.7.2.3