]> git.puffer.fish Git - mirror/frr.git/commitdiff
vrrpd: elect self to Master when owning v4 address
authorQuentin Young <qlyoung@cumulusnetworks.com>
Mon, 10 Dec 2018 22:16:10 +0000 (22:16 +0000)
committerQuentin Young <qlyoung@cumulusnetworks.com>
Fri, 17 May 2019 00:27:08 +0000 (00:27 +0000)
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 <qlyoung@cumulusnetworks.com>
vrrpd/vrrp.c
vrrpd/vrrp.h

index 0fd5e254818722922a2e2b0aef92f7ac3207e32b..bf43255d1c003989e0c4fafd79dbfa0890af367a 100644 (file)
@@ -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);
index 6ce0e03bf4e3f04344e2422ffadf28122b617053..b86aba993985f31d21a8baa8646251d4b0abc27c 100644 (file)
@@ -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