]> git.puffer.fish Git - matthieu/frr.git/commitdiff
vrrpd: autoconfig support
authorQuentin Young <qlyoung@cumulusnetworks.com>
Thu, 7 Feb 2019 23:48:49 +0000 (23:48 +0000)
committerQuentin Young <qlyoung@cumulusnetworks.com>
Fri, 17 May 2019 00:27:08 +0000 (00:27 +0000)
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
lib/if.h
lib/zclient.c
vrrpd/vrrp.c
vrrpd/vrrp.h
vrrpd/vrrp_vty.c
vrrpd/vrrp_zebra.c
zebra/zapi_msg.c

index ef596d45dc00035ad8f6e490bcaff241733e5de1..2dc1a7b2de237a6e9c4849499aa8b0089ac1fa9e 100644 (file)
--- a/lib/if.h
+++ b/lib/if.h
@@ -225,6 +225,10 @@ struct interface {
           not work as expected.
         */
        ifindex_t ifindex;
+       /*
+        * ifindex of parent interface, if any
+        */
+       ifindex_t link_ifindex;
 #define IFINDEX_INTERNAL       0
 
        /* Zebra internal interface status */
index 6647a1ab189b10b29bde840dfbf1469139e22839..0972590ca695e9dfd70a1102e22dca1301c8b7c7 100644 (file)
@@ -1400,6 +1400,8 @@ stream_failure:
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * |  bandwidth                                                    |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |  parent ifindex                                               |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * |  Link Layer Type                                              |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * |  Harware Address Length                                       |
@@ -1580,6 +1582,7 @@ void zebra_interface_if_set_value(struct stream *s, struct interface *ifp)
        ifp->mtu = stream_getl(s);
        ifp->mtu6 = stream_getl(s);
        ifp->bandwidth = stream_getl(s);
+       ifp->link_ifindex = stream_getl(s);
        ifp->ll_type = stream_getl(s);
        ifp->hw_addr_len = stream_getl(s);
        if (ifp->hw_addr_len)
index 265cce33fb11789c4355095614e1315748efcfa7..bf804abb3d0d1f7339d2bde0ed0f92663c9114a4 100644 (file)
@@ -1297,6 +1297,81 @@ int vrrp_event(struct vrrp_router *r, int event)
 
 /* Other ------------------------------------------------------------------- */
 
+static struct vrrp_vrouter *
+vrrp_autoconfig_autocreate(struct interface *mvl_ifp)
+{
+       struct interface *p;
+       struct vrrp_vrouter *vr;
+
+       p = if_lookup_by_index(mvl_ifp->link_ifindex, VRF_DEFAULT);
+       uint8_t vrid = mvl_ifp->hw_addr[5];
+
+       zlog_info(VRRP_LOGPFX "Autoconfiguring VRRP on %s", p->name);
+
+       /* If it already exists, skip it */
+       vr = vrrp_lookup(p, vrid);
+       if (vr) {
+               zlog_info(VRRP_LOGPFX "VRRP instance %" PRIu8
+                                     "already configured on %s",
+                         vrid, p->name);
+               return vr;
+       }
+
+       /* create a new one */
+       vr = vrrp_vrouter_create(p, vrid, vrrp_autoconfig_version);
+
+       if (!vr)
+               return NULL;
+
+       /* add connected addresses as vips */
+       struct listnode *ln;
+       struct connected *c = NULL;
+       for (ALL_LIST_ELEMENTS_RO(mvl_ifp->connected, ln, c))
+               if (c->address->family == AF_INET)
+                       vrrp_add_ipv4(vr, c->address->u.prefix4, false);
+               else if (c->address->family == AF_INET6) {
+                       if (!IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6))
+                               vrrp_add_ipv6(vr, c->address->u.prefix6, false);
+               }
+
+       if (vr->v4->addrs->count)
+               vrrp_event(vr->v4, VRRP_EVENT_STARTUP);
+       if (vr->v6->addrs->count)
+               vrrp_event(vr->v6, VRRP_EVENT_STARTUP);
+
+       vr->autoconf = true;
+
+       return vr;
+}
+
+static bool vrrp_ifp_is_mvl(struct interface *ifp)
+{
+       struct ethaddr vmac4;
+       struct ethaddr vmac6;
+       vrrp_mac_set(&vmac4, 0, 0x00);
+       vrrp_mac_set(&vmac6, 1, 0x00);
+
+       return !memcmp(ifp->hw_addr, vmac4.octet, sizeof(vmac4.octet) - 1)
+              || !memcmp(ifp->hw_addr, vmac6.octet, sizeof(vmac6.octet) - 1);
+}
+
+int vrrp_autoconfig(struct interface *ifp)
+{
+       if (ifp && vrrp_ifp_is_mvl(ifp)) {
+               vrrp_autoconfig_autocreate(ifp);
+               return 0;
+       }
+
+       /* Loop through interfaces, looking for compatible macvlan devices. */
+       struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+
+       FOR_ALL_INTERFACES (vrf, ifp)
+               if (vrrp_ifp_is_mvl(ifp))
+                       vrrp_autoconfig_autocreate(ifp);
+
+       return 0;
+}
+
 static unsigned int vrrp_hash_key(void *arg)
 {
        struct vrrp_vrouter *vr = arg;
@@ -1323,6 +1398,7 @@ static bool vrrp_hash_cmp(const void *arg1, const void *arg2)
 
 void vrrp_init(void)
 {
+       vrrp_autoconfig_version = 3;
        vrrp_vrouters_hash = hash_create(&vrrp_hash_key, vrrp_hash_cmp,
                                         "VRRP virtual router hash");
        vrf_init(NULL, NULL, NULL, NULL, NULL);
index 0df588b2210dc21c8863f2e4413359e454492a2a..57ec55eea45e5b060b27b7c03b38cba6527d35e3 100644 (file)
@@ -53,13 +53,17 @@ extern struct zebra_privs_t vrrp_privs;
 /* Global hash of all Virtual Routers */
 struct hash *vrrp_vrouters_hash;
 
-/*
- * VRRP Router.
- *
- * This struct contains all state for a particular VRRP Router operating in a
- * Virtual Router for either IPv4 or IPv6.
- */
-struct vrrp_router {
+/* Whether to automatically configure VRRP instances */
+static bool vrrp_autoconfig_on;
+static int vrrp_autoconfig_version;
+
+       /*
+        * VRRP Router.
+        *
+        * This struct contains all state for a particular VRRP Router operating
+        * in a Virtual Router for either IPv4 or IPv6.
+        */
+       struct vrrp_router {
        /*
         * Whether this VRRP Router is active.
         */
@@ -164,6 +168,9 @@ struct vrrp_router {
  * implementations.
  */
 struct vrrp_vrouter {
+       /* Whether this instance was automatically configured */
+       bool autoconf;
+
        /* Interface */
        struct interface *ifp;
 
@@ -417,6 +424,23 @@ int vrrp_event(struct vrrp_router *r, int event);
 
 /* Other ------------------------------------------------------------------- */
 
+/*
+ * Search for and automatically configure VRRP instances on interfaces.
+ *
+ * ifp
+ *    Interface to autoconfig. If it is a macvlan interface and has a VRRP MAC,
+ *    a VRRP instance corresponding to VMAC assigned to macvlan will be created
+ *    on the parent interface and all addresses on the macvlan interface except
+ *    the v6 link local will be configured as VRRP addresses. If NULL, this
+ *    treatment will be applied to all existing interfaces matching the above
+ *    criterion.
+ *
+ * Returns:
+ *    -1 on failure
+ *     0 otherwise
+ */
+int vrrp_autoconfig(struct interface *ifp);
+
 /*
  * Find VRRP Virtual Router by Virtual Router ID
  */
index 70711d12a9eff7489177a9bcea21f8c3aa25c900..c73e5cb55632254923eccbc536ae358f010fb48f 100644 (file)
@@ -287,6 +287,26 @@ DEFPY(vrrp_preempt,
        return CMD_SUCCESS;
 }
 
+DEFPY(vrrp_autoconf,
+      vrrp_autoconf_cmd,
+      "[no] vrrp autoconfig [version (2-3)]",
+      NO_STR
+      VRRP_STR
+      "Automatically set up VRRP instances on VRRP-compatible interfaces\n"
+      "Version for automatically configured instances\n"
+      VRRP_VERSION_STR)
+{
+       vrrp_autoconfig_on = !no;
+       version = version ? version : 3;
+
+       if (vrrp_autoconfig_on)
+               vrrp_autoconfig(NULL);
+
+       vrrp_autoconfig_version = !no ? version : vrrp_autoconfig_version;
+
+       return CMD_SUCCESS;
+}
+
 static void vrrp_show(struct vty *vty, struct vrrp_vrouter *vr)
 {
        char ethstr4[ETHER_ADDR_STRLEN];
@@ -401,6 +421,7 @@ void vrrp_vty_init(void)
        if_cmd_init();
        install_element(VIEW_NODE, &show_debugging_vrrpd_cmd);
        install_element(VIEW_NODE, &vrrp_vrid_show_cmd);
+       install_element(CONFIG_NODE, &vrrp_autoconf_cmd);
        install_element(INTERFACE_NODE, &vrrp_vrid_cmd);
        install_element(INTERFACE_NODE, &vrrp_priority_cmd);
        install_element(INTERFACE_NODE, &vrrp_advertisement_interval_cmd);
index c41915cbd95eca9b1bfb2d08c93f183c40b12fc1..e7967f93264a953c139555641b175214d8d34ca3 100644 (file)
@@ -61,7 +61,8 @@ static int vrrp_zebra_if_add(int command, struct zclient *zclient,
        if (!ifp)
                return 0;
 
-       /* FIXME: handle subinterface creation here */
+       if (vrrp_autoconfig_on)
+               vrrp_autoconfig(ifp);
 
        return 0;
 }
index a497331702981c5a1706cc8bf09f08ef2ad8b9b0..ca371186b7735dbd86bae58a1eb7fd33a1bac740 100644 (file)
@@ -71,6 +71,7 @@
 static void zserv_encode_interface(struct stream *s, struct interface *ifp)
 {
        /* Interface information. */
+       struct zebra_if *zif = ifp->info;
        stream_put(s, ifp->name, INTERFACE_NAMSIZ);
        stream_putl(s, ifp->ifindex);
        stream_putc(s, ifp->status);
@@ -82,6 +83,7 @@ static void zserv_encode_interface(struct stream *s, struct interface *ifp)
        stream_putl(s, ifp->mtu);
        stream_putl(s, ifp->mtu6);
        stream_putl(s, ifp->bandwidth);
+       stream_putl(s, zif->link_ifindex);
        stream_putl(s, ifp->ll_type);
        stream_putl(s, ifp->hw_addr_len);
        if (ifp->hw_addr_len)