From 5d3730c5f14c4cf60d965093ff4945101092be9e Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Mon, 10 Dec 2018 22:16:10 +0000 Subject: [PATCH] vrrpd: elect self to Master when owning v4 address If the primary address is v4, and we own the address on our configured interface, set ourselves to Master. This introduces the concept of a separate priority value used to store the configured vs effective priority. Signed-off-by: Quentin Young --- vrrpd/vrrp.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++------ vrrpd/vrrp.h | 17 ++++++++++----- 2 files changed, 65 insertions(+), 11 deletions(-) diff --git a/vrrpd/vrrp.c b/vrrpd/vrrp.c index 0fd5e25481..bf43255d1c 100644 --- a/vrrpd/vrrp.c +++ b/vrrpd/vrrp.c @@ -105,17 +105,44 @@ static void vrrp_reset_times(struct vrrp_vrouter *vr) vrrp_update_times(vr, vr->advertisement_interval, 0); } +/* + * Determines if a VRRP router is the owner of the specified address. + * + * vr + * VRRP router + * + * Returns: + * whether or not vr owns the specified address + */ +static bool vrrp_is_owner(struct vrrp_vrouter *vr, struct ipaddr *addr) +{ + struct prefix *p; + struct prefix_ipv4 p4; + struct prefix_ipv6 p6; + + if (IS_IPADDR_V4(addr)) { + p4.family = AF_INET; + p4.prefixlen = IPV4_MAX_BITLEN; + p4.prefix = addr->ipaddr_v4; + p = (struct prefix *)&p4; + } else { + p6.family = AF_INET6; + p6.prefixlen = IPV6_MAX_BITLEN; + memcpy(&p6.prefix, &addr->ipaddr_v6, sizeof(struct in6_addr)); + p = (struct prefix *)&p6; + } + + return !!connected_lookup_prefix_exact(vr->ifp, p); +} + /* Configuration controllers ----------------------------------------------- */ void vrrp_set_priority(struct vrrp_vrouter *vr, uint8_t priority) { - if (vr->priority == priority) + if (vr->priority_conf == priority) return; - vr->priority = priority; - /* Timers depend on priority value, need to recalculate them */ - vrrp_update_times(vr, vr->advertisement_interval, - vr->master_adver_interval); + vr->priority_conf = priority; } void vrrp_set_advertisement_interval(struct vrrp_vrouter *vr, @@ -148,7 +175,7 @@ struct vrrp_vrouter *vrrp_vrouter_create(struct interface *ifp, uint8_t vrid) vr->vrid = vrid; vr->v4 = list_new(); vr->v6 = list_new(); - vr->is_master = false; + vr->priority_conf = VRRP_DEFAULT_PRIORITY; vr->priority = VRRP_DEFAULT_PRIORITY; vr->preempt_mode = true; vr->accept_mode = false; @@ -421,6 +448,26 @@ static int vrrp_startup(struct vrrp_vrouter *vr) /* Schedule listener */ /* ... */ + /* configure effective priority */ + struct in_addr *primary = (struct in_addr *) listhead(vr->v4)->data; + struct ipaddr primary_ipaddr; + primary_ipaddr.ipa_type = IPADDR_V4; + primary_ipaddr.ipaddr_v4 = *primary; + + char ipbuf[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, primary, ipbuf, sizeof(ipbuf)); + + if (vrrp_is_owner(vr, &primary_ipaddr)) { + vr->priority = VRRP_PRIO_MASTER; + /* Timers depend on priority value, need to recalculate them */ + vrrp_update_times(vr, vr->advertisement_interval, + vr->master_adver_interval); + zlog_info( + VRRP_LOGPFX VRRP_LOGPFX_VRID + "%s owns primary Virtual Router IP %s; electing self as Master", + vr->vrid, vr->ifp->name, ipbuf); + } + if (vr->priority == VRRP_PRIO_MASTER) { vrrp_send_advertisement(vr); vrrp_garp_send_all(vr); diff --git a/vrrpd/vrrp.h b/vrrpd/vrrp.h index 6ce0e03bf4..b86aba9939 100644 --- a/vrrpd/vrrp.h +++ b/vrrpd/vrrp.h @@ -71,10 +71,14 @@ struct vrrp_vrouter { */ struct list *v6; - /* Whether this VRRP Router is currently the master */ - bool is_master; + /* Configured priority */ + uint8_t priority_conf; - /* Priority */ + /* + * Effective priority + * => priority if we are Backup + * => 255 if we are Master + */ uint8_t priority; /* @@ -159,9 +163,12 @@ void vrrp_vrouter_destroy(struct vrrp_vrouter *vr); /* Configuration controllers ----------------------------------------------- */ /* - * Change the priority of a VRRP Virtual Router. + * Change the configured priority of a VRRP Virtual Router. * - * Also recalculates timers using new priority. + * Note that this only changes the configured priority of the Virtual Router. + * The currently effective priority will not be changed; to change the + * effective priority, the Virtual Router must be restarted by issuing a + * VRRP_EVENT_SHUTDOWN followed by a VRRP_EVENT_STARTUP. * * vr * Virtual Router to change priority of -- 2.39.5