]> git.puffer.fish Git - mirror/frr.git/commitdiff
pimd : Add support for MLAG Register & Un-register
authorSatheesh Kumar K <sathk@cumulusnetworks.com>
Tue, 12 Nov 2019 06:36:17 +0000 (22:36 -0800)
committerSatheesh Kumar K <sathk@cumulusnetworks.com>
Thu, 14 Nov 2019 03:46:52 +0000 (19:46 -0800)
when ever a FRR Client wants to send any data to another node
using MLAG Channel, uses below mechanisam.

1. sends  a MLAG Registration to zebra with interested messages that
   it is intended to receive from peer.
2. In response to this request, Zebra opens communication channel with
   MLAG. and also in Rx. diretion zebra forwards only those messages which
   client shown interest during registration
3. when client is no-longer interested in communicating with MLAG, client
   posts De-register to Zebra
4. if this is the last client which is interested for MLAG Communication,
   zebra closes the channel.

why PIM Needs MLAG Communication
================================
1. In general on LAN Networks elecetd DR will send the Join towards
   Multicast RP in case of a LHR and Register in case of FHR.
2. But in case DR Goes down, traffic will be re-converged only after
   the New DR is elected, but this can take time based on Hold Timer to
   detect the DR down.
3. this can be optimised by using MLAG Mecganisam.
4. and also Traffic can be forwarded more efficiently by knowing the cost
   towards RP using MLAG

Signed-off-by: Satheesh Kumar K <sathk@cumulusnetworks.com>
13 files changed:
lib/mlag.h
lib/zclient.c
lib/zclient.h
pimd/pim_cmd.c
pimd/pim_cmd.h
pimd/pim_instance.c
pimd/pim_instance.h
pimd/pim_main.c
pimd/pim_mlag.c [new file with mode: 0644]
pimd/pim_mlag.h [new file with mode: 0644]
pimd/pim_zebra.c
pimd/pimd.h
pimd/subdir.am

index 2b904d44f463c31a267c77c2471e8e1b6c14486d..d461fdc44e99944ad95cf9dfc2da2c372a2dc6a3 100644 (file)
 extern "C" {
 #endif
 
+#define MLAG_BUF_LIMIT 2048
+
 enum mlag_role {
        MLAG_ROLE_NONE,
        MLAG_ROLE_PRIMARY,
        MLAG_ROLE_SECONDARY
 };
 
+/*
+ * This message definition should match mlag.proto
+ * Beacuse mesasge registartion is based on this
+ */
+enum mlag_msg_type {
+       MLAG_MSG_NONE = 0,
+       MLAG_REGISTER = 1,
+       MLAG_DEREGISTER = 2,
+       MLAG_STATUS_UPDATE = 3,
+       MLAG_MROUTE_ADD = 4,
+       MLAG_MROUTE_DEL = 5,
+       MLAG_DUMP = 6,
+       MLAG_MROUTE_ADD_BULK = 7,
+       MLAG_MROUTE_DEL_BULK = 8,
+       MLAG_PIM_CFG_DUMP = 10,
+       MLAG_VXLAN_UPDATE = 11,
+       MLAG_PEER_FRR_STATUS = 12,
+};
+
 extern char *mlag_role2str(enum mlag_role role, char *buf, size_t size);
 
 #ifdef __cplusplus
index a135d18744002bf84ca72417f1971da10f17cf7c..1540fafb5d91169cde568939fbfd6e6436f5fedc 100644 (file)
@@ -2721,6 +2721,39 @@ stream_failure:
        return;
 }
 
+void zclient_send_mlag_register(struct zclient *client, uint32_t bit_map)
+{
+       struct stream *s;
+
+       s = client->obuf;
+       stream_reset(s);
+
+       zclient_create_header(s, ZEBRA_MLAG_CLIENT_REGISTER, VRF_DEFAULT);
+       stream_putl(s, bit_map);
+
+       stream_putw_at(s, 0, stream_get_endp(s));
+       zclient_send_message(client);
+}
+
+void zclient_send_mlag_deregister(struct zclient *client)
+{
+       zebra_message_send(client, ZEBRA_MLAG_CLIENT_UNREGISTER, VRF_DEFAULT);
+}
+
+void zclient_send_mlag_data(struct zclient *client, struct stream *client_s)
+{
+       struct stream *s;
+
+       s = client->obuf;
+       stream_reset(s);
+
+       zclient_create_header(s, ZEBRA_MLAG_FORWARD_MSG, VRF_DEFAULT);
+       stream_put(s, client_s->data, client_s->endp);
+
+       stream_putw_at(s, 0, stream_get_endp(s));
+       zclient_send_message(client);
+}
+
 /* Zebra client message read function. */
 static int zclient_read(struct thread *thread)
 {
index 2131d4d47a7de18cfb8b6559a69103786c8c8590..6cb09a6ac7e5b69ffd6903aaa47ce47e322ec9dd 100644 (file)
@@ -178,6 +178,9 @@ typedef enum {
        ZEBRA_VXLAN_SG_ADD,
        ZEBRA_VXLAN_SG_DEL,
        ZEBRA_VXLAN_SG_REPLAY,
+       ZEBRA_MLAG_CLIENT_REGISTER,
+       ZEBRA_MLAG_CLIENT_UNREGISTER,
+       ZEBRA_MLAG_FORWARD_MSG,
 } zebra_message_types_t;
 
 struct redist_proto {
@@ -694,5 +697,11 @@ static inline void zapi_route_set_blackhole(struct zapi_route *api,
        SET_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP);
 };
 
+extern void zclient_send_mlag_register(struct zclient *client,
+                                      uint32_t bit_map);
+extern void zclient_send_mlag_deregister(struct zclient *client);
+
+extern void zclient_send_mlag_data(struct zclient *client,
+                                  struct stream *client_s);
 
 #endif /* _ZEBRA_ZCLIENT_H */
index e5686a94f44bc34c3a51162343cb2c718c2c0543..0403a471f5a9f60ffded45a2807cbdd43c63a793 100644 (file)
@@ -61,6 +61,7 @@
 #include "pim_nht.h"
 #include "pim_bfd.h"
 #include "pim_vxlan.h"
+#include "pim_mlag.h"
 #include "bfd.h"
 #include "pim_bsm.h"
 
@@ -7458,9 +7459,9 @@ DEFPY_HIDDEN (interface_ip_pim_activeactive,
 
        pim_ifp = ifp->info;
        if (no)
-               pim_ifp->activeactive = false;
+               pim_if_unconfigure_mlag_dualactive(pim_ifp);
        else
-               pim_ifp->activeactive = true;
+               pim_if_configure_mlag_dualactive(pim_ifp);
 
        return CMD_SUCCESS;
 }
@@ -8378,6 +8379,20 @@ DEFUN (no_debug_pim_zebra,
        return CMD_SUCCESS;
 }
 
+DEFUN(debug_pim_mlag, debug_pim_mlag_cmd, "debug pim mlag",
+      DEBUG_STR DEBUG_PIM_STR DEBUG_PIM_MLAG_STR)
+{
+       PIM_DO_DEBUG_MLAG;
+       return CMD_SUCCESS;
+}
+
+DEFUN(no_debug_pim_mlag, no_debug_pim_mlag_cmd, "no debug pim mlag",
+      NO_STR DEBUG_STR DEBUG_PIM_STR DEBUG_PIM_MLAG_STR)
+{
+       PIM_DONT_DEBUG_MLAG;
+       return CMD_SUCCESS;
+}
+
 DEFUN (debug_pim_vxlan,
        debug_pim_vxlan_cmd,
        "debug pim vxlan",
@@ -10404,6 +10419,8 @@ void pim_cmd_init(void)
        install_element(ENABLE_NODE, &no_debug_ssmpingd_cmd);
        install_element(ENABLE_NODE, &debug_pim_zebra_cmd);
        install_element(ENABLE_NODE, &no_debug_pim_zebra_cmd);
+       install_element(ENABLE_NODE, &debug_pim_mlag_cmd);
+       install_element(ENABLE_NODE, &no_debug_pim_mlag_cmd);
        install_element(ENABLE_NODE, &debug_pim_vxlan_cmd);
        install_element(ENABLE_NODE, &no_debug_pim_vxlan_cmd);
        install_element(ENABLE_NODE, &debug_msdp_cmd);
index f5bb316a7ae3b3648d6b7641db30566a700b3187..89a4e6e69903f82472759348f7658b3244aa0066 100644 (file)
@@ -54,6 +54,7 @@
 #define DEBUG_PIM_PACKETDUMP_RECV_STR               "Dump received packets\n"
 #define DEBUG_PIM_TRACE_STR                         "PIM internal daemon activity\n"
 #define DEBUG_PIM_ZEBRA_STR                         "ZEBRA protocol activity\n"
+#define DEBUG_PIM_MLAG_STR                          "PIM Mlag activity\n"
 #define DEBUG_PIM_VXLAN_STR                         "PIM VxLAN events\n"
 #define DEBUG_SSMPINGD_STR                          "ssmpingd activity\n"
 #define CLEAR_IP_IGMP_STR                           "IGMP clear commands\n"
index 6848d2dabb73a7d95df03db2703e85d1add827d8..955ad14b010f36d16b48ccb65d55af98b416ebaa 100644 (file)
@@ -34,6 +34,7 @@
 #include "pim_ssmpingd.h"
 #include "pim_vty.h"
 #include "pim_bsm.h"
+#include "pim_mlag.h"
 
 static void pim_instance_terminate(struct pim_instance *pim)
 {
@@ -47,6 +48,8 @@ static void pim_instance_terminate(struct pim_instance *pim)
        if (pim->static_routes)
                list_delete(&pim->static_routes);
 
+       pim_instance_mlag_terminate(pim);
+
        pim_upstream_terminate(pim);
 
        pim_rp_free(pim);
@@ -115,6 +118,8 @@ static struct pim_instance *pim_instance_init(struct vrf *vrf)
 
        pim_upstream_init(pim);
 
+       pim_instance_mlag_init(pim);
+
        pim->last_route_change_time = -1;
        return pim;
 }
index 06d41c4b537d392397e8b8d1ee82d31223bf04b1..dd3ac8fcb07bfcb6c1759cdf40158d93b7eba041 100644 (file)
@@ -64,6 +64,17 @@ struct pim_router {
        vrf_id_t vrf_id;
 
        enum mlag_role role;
+       uint32_t pim_mlag_intf_cnt;
+       /* if true we have registered with MLAG */
+       bool mlag_process_register;
+       /* if true local MLAG process reported that it is connected
+        * with the peer MLAG process
+        */
+       bool connected_to_mlag;
+       /* Holds the client data(unencoded) that need to be pushed to MCLAGD*/
+       struct stream_fifo *mlag_fifo;
+       struct stream *mlag_stream;
+       struct thread *zpthread_mlag_write;
 };
 
 /* Per VRF PIM DB */
@@ -122,6 +133,9 @@ struct pim_instance {
 
        bool ecmp_enable;
        bool ecmp_rebalance_enable;
+       /* No. of Dual active I/fs in pim_instance */
+       uint32_t inst_mlag_intf_cnt;
+
        /* Bsm related */
        struct bsm_scope global_scope;
        uint64_t bsm_rcvd;
index 6a7dbe769ff26e79e43817bb1f2209834ee0f77a..4090ce7f9325eecb0d56309ef2d26900e8327ddd 100644 (file)
@@ -47,6 +47,7 @@
 #include "pim_msdp.h"
 #include "pim_iface.h"
 #include "pim_bfd.h"
+#include "pim_mlag.h"
 #include "pim_errors.h"
 
 extern struct host host;
@@ -131,6 +132,7 @@ int main(int argc, char **argv, char **envp)
                          pim_ifp_down, pim_ifp_destroy);
        pim_zebra_init();
        pim_bfd_init();
+       pim_mlag_init();
 
        frr_config_fork();
 
diff --git a/pimd/pim_mlag.c b/pimd/pim_mlag.c
new file mode 100644 (file)
index 0000000..5e5da29
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * This is an implementation of PIM MLAG Functionality
+ *
+ * Module name: PIM MLAG
+ *
+ * Author: sathesh Kumar karra <sathk@cumulusnetworks.com>
+ *
+ * Copyright (C) 2019 Cumulus Networks http://www.cumulusnetworks.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <zebra.h>
+
+#include "pimd.h"
+#include "pim_mlag.h"
+
+extern struct zclient *zclient;
+
+static int pim_mlag_register_handler(struct thread *thread)
+{
+       uint32_t bit_mask = 0;
+
+       if (!zclient)
+               return -1;
+
+       SET_FLAG(bit_mask, (1 << MLAG_STATUS_UPDATE));
+       SET_FLAG(bit_mask, (1 << MLAG_MROUTE_ADD));
+       SET_FLAG(bit_mask, (1 << MLAG_MROUTE_DEL));
+       SET_FLAG(bit_mask, (1 << MLAG_DUMP));
+       SET_FLAG(bit_mask, (1 << MLAG_MROUTE_ADD_BULK));
+       SET_FLAG(bit_mask, (1 << MLAG_MROUTE_DEL_BULK));
+       SET_FLAG(bit_mask, (1 << MLAG_PIM_CFG_DUMP));
+       SET_FLAG(bit_mask, (1 << MLAG_VXLAN_UPDATE));
+       SET_FLAG(bit_mask, (1 << MLAG_PEER_FRR_STATUS));
+
+       if (PIM_DEBUG_MLAG)
+               zlog_debug("%s: Posting Client Register to MLAG mask: 0x%x",
+                          __func__, bit_mask);
+
+       zclient_send_mlag_register(zclient, bit_mask);
+       return 0;
+}
+
+void pim_mlag_register(void)
+{
+       if (router->mlag_process_register)
+               return;
+
+       router->mlag_process_register = true;
+
+       thread_add_event(router->master, pim_mlag_register_handler, NULL, 0,
+                        NULL);
+}
+
+static int pim_mlag_deregister_handler(struct thread *thread)
+{
+       if (!zclient)
+               return -1;
+
+       if (PIM_DEBUG_MLAG)
+               zlog_debug("%s: Posting Client De-Register to MLAG from PIM",
+                          __func__);
+       router->connected_to_mlag = false;
+       zclient_send_mlag_deregister(zclient);
+       return 0;
+}
+
+void pim_mlag_deregister(void)
+{
+       /* if somebody still interested in the MLAG channel skip de-reg */
+       if (router->pim_mlag_intf_cnt)
+               return;
+
+       /* not registered; nothing do */
+       if (!router->mlag_process_register)
+               return;
+
+       router->mlag_process_register = false;
+
+       thread_add_event(router->master, pim_mlag_deregister_handler, NULL, 0,
+                        NULL);
+}
+
+void pim_if_configure_mlag_dualactive(struct pim_interface *pim_ifp)
+{
+       if (!pim_ifp || !pim_ifp->pim || pim_ifp->activeactive == true)
+               return;
+
+       if (PIM_DEBUG_MLAG)
+               zlog_debug("%s: Configuring active-active on Interface: %s",
+                          __func__, "NULL");
+
+       pim_ifp->activeactive = true;
+       if (pim_ifp->pim)
+               pim_ifp->pim->inst_mlag_intf_cnt++;
+
+       router->pim_mlag_intf_cnt++;
+       if (PIM_DEBUG_MLAG)
+               zlog_debug(
+                       "%s: Total MLAG configured Interfaces on router: %d, Inst: %d",
+                       __func__, router->pim_mlag_intf_cnt,
+                       pim_ifp->pim->inst_mlag_intf_cnt);
+
+       if (router->pim_mlag_intf_cnt == 1) {
+               /*
+                * atleast one Interface is configured for MLAG, send register
+                * to Zebra for receiving MLAG Updates
+                */
+               pim_mlag_register();
+       }
+}
+
+void pim_if_unconfigure_mlag_dualactive(struct pim_interface *pim_ifp)
+{
+       if (!pim_ifp || !pim_ifp->pim || pim_ifp->activeactive == false)
+               return;
+
+       if (PIM_DEBUG_MLAG)
+               zlog_debug("%s: UnConfiguring active-active on Interface: %s",
+                          __func__, "NULL");
+
+       pim_ifp->activeactive = false;
+       if (pim_ifp->pim)
+               pim_ifp->pim->inst_mlag_intf_cnt--;
+
+       router->pim_mlag_intf_cnt--;
+       if (PIM_DEBUG_MLAG)
+               zlog_debug(
+                       "%s: Total MLAG configured Interfaces on router: %d, Inst: %d",
+                       __func__, router->pim_mlag_intf_cnt,
+                       pim_ifp->pim->inst_mlag_intf_cnt);
+
+       if (router->pim_mlag_intf_cnt == 0) {
+               /*
+                * all the Interfaces are MLAG un-configured, post MLAG
+                * De-register to Zebra
+                */
+               pim_mlag_deregister();
+       }
+}
+
+
+void pim_instance_mlag_init(struct pim_instance *pim)
+{
+       if (!pim)
+               return;
+
+       pim->inst_mlag_intf_cnt = 0;
+}
+
+
+void pim_instance_mlag_terminate(struct pim_instance *pim)
+{
+       struct interface *ifp;
+
+       if (!pim)
+               return;
+
+       FOR_ALL_INTERFACES (pim->vrf, ifp) {
+               struct pim_interface *pim_ifp = ifp->info;
+
+               if (!pim_ifp || pim_ifp->activeactive == false)
+                       continue;
+
+               pim_if_unconfigure_mlag_dualactive(pim_ifp);
+       }
+       pim->inst_mlag_intf_cnt = 0;
+}
+
+void pim_mlag_init(void)
+{
+       router->pim_mlag_intf_cnt = 0;
+       router->connected_to_mlag = false;
+       router->mlag_fifo = stream_fifo_new();
+       router->zpthread_mlag_write = NULL;
+       router->mlag_stream = stream_new(MLAG_BUF_LIMIT);
+}
diff --git a/pimd/pim_mlag.h b/pimd/pim_mlag.h
new file mode 100644 (file)
index 0000000..b1c3fce
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * This is an implementation of PIM MLAG Functionality
+ *
+ * Module name: PIM MLAG
+ *
+ * Author: sathesh Kumar karra <sathk@cumulusnetworks.com>
+ *
+ * Copyright (C) 2019 Cumulus Networks http://www.cumulusnetworks.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __PIM_MLAG_H__
+#define __PIM_MLAG_H__
+
+#include "mlag.h"
+#include "pim_iface.h"
+
+extern void pim_mlag_init(void);
+extern void pim_instance_mlag_init(struct pim_instance *pim);
+extern void pim_instance_mlag_terminate(struct pim_instance *pim);
+extern void pim_if_configure_mlag_dualactive(struct pim_interface *pim_ifp);
+extern void pim_if_unconfigure_mlag_dualactive(struct pim_interface *pim_ifp);
+extern void pim_mlag_register(void);
+extern void pim_mlag_deregister(void);
+#endif
index dfddee99d044ead2681e2f827532193f26c8e7ec..ede37ec53e8dbc080d51b18f324d81476e1de67c 100644 (file)
@@ -50,7 +50,7 @@
 #undef PIM_DEBUG_IFADDR_DUMP
 #define PIM_DEBUG_IFADDR_DUMP
 
-static struct zclient *zclient = NULL;
+struct zclient *zclient;
 
 
 /* Router-id update message from zebra. */
index 3b83d3b6c7df16b43f550ac81258f6a7fe94390a..70d276622080c1fb8a40b0618d4588216e296ef3 100644 (file)
 #define PIM_MASK_MTRACE              (1 << 25)
 #define PIM_MASK_VXLAN               (1 << 26)
 #define PIM_MASK_BSM_PROC            (1 << 27)
+#define PIM_MASK_MLAG                (1 << 28)
 /* Remember 32 bits!!! */
 
 /* PIM error codes */
@@ -171,6 +172,7 @@ extern uint8_t qpim_ecmp_rebalance_enable;
 #define PIM_DEBUG_IGMP_TRACE_DETAIL                                            \
        (router->debugs & (PIM_MASK_IGMP_TRACE_DETAIL | PIM_MASK_IGMP_TRACE))
 #define PIM_DEBUG_ZEBRA (router->debugs & PIM_MASK_ZEBRA)
+#define PIM_DEBUG_MLAG (router->debugs & PIM_MASK_MLAG)
 #define PIM_DEBUG_SSMPINGD (router->debugs & PIM_MASK_SSMPINGD)
 #define PIM_DEBUG_MROUTE (router->debugs & PIM_MASK_MROUTE)
 #define PIM_DEBUG_MROUTE_DETAIL                                                \
@@ -217,6 +219,7 @@ extern uint8_t qpim_ecmp_rebalance_enable;
 #define PIM_DO_DEBUG_IGMP_TRACE_DETAIL                                         \
        (router->debugs |= PIM_MASK_IGMP_TRACE_DETAIL)
 #define PIM_DO_DEBUG_ZEBRA (router->debugs |= PIM_MASK_ZEBRA)
+#define PIM_DO_DEBUG_MLAG (router->debugs |= PIM_MASK_MLAG)
 #define PIM_DO_DEBUG_SSMPINGD (router->debugs |= PIM_MASK_SSMPINGD)
 #define PIM_DO_DEBUG_MROUTE (router->debugs |= PIM_MASK_MROUTE)
 #define PIM_DO_DEBUG_MROUTE_DETAIL (router->debugs |= PIM_MASK_MROUTE_DETAIL)
@@ -248,6 +251,7 @@ extern uint8_t qpim_ecmp_rebalance_enable;
 #define PIM_DONT_DEBUG_IGMP_TRACE_DETAIL                                       \
        (router->debugs &= ~PIM_MASK_IGMP_TRACE_DETAIL)
 #define PIM_DONT_DEBUG_ZEBRA (router->debugs &= ~PIM_MASK_ZEBRA)
+#define PIM_DONT_DEBUG_MLAG (router->debugs &= ~PIM_MASK_MLAG)
 #define PIM_DONT_DEBUG_SSMPINGD (router->debugs &= ~PIM_MASK_SSMPINGD)
 #define PIM_DONT_DEBUG_MROUTE (router->debugs &= ~PIM_MASK_MROUTE)
 #define PIM_DONT_DEBUG_MROUTE_DETAIL (router->debugs &= ~PIM_MASK_MROUTE_DETAIL)
index 240b62804fb7a2fea15ba5b8769ca93429ef37d3..5407e566a5ad89acc4ee8ae6a4db251c38725680 100644 (file)
@@ -62,6 +62,7 @@ pimd_libpim_a_SOURCES = \
        pimd/pim_zebra.c \
        pimd/pim_zlookup.c \
        pimd/pim_vxlan.c \
+       pimd/pim_mlag.c \
        pimd/pimd.c \
        # end
 
@@ -114,6 +115,7 @@ noinst_HEADERS += \
        pimd/pim_zebra.h \
        pimd/pim_zlookup.h \
        pimd/pim_vxlan.h \
+       pimd/pim_mlag.h \
        pimd/pim_vxlan_instance.h \
        pimd/pimd.h \
        pimd/mtracebis_netlink.h \