summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pimd/pim_cmd.c269
-rw-r--r--pimd/pim_ifchannel.c3
-rw-r--r--pimd/pim_mlag.c19
-rw-r--r--pimd/pim_mlag.h6
-rw-r--r--pimd/pim_oil.c5
-rw-r--r--pimd/pim_oil.h4
-rw-r--r--pimd/pim_vty.c5
-rw-r--r--pimd/pim_zpthread.c225
-rw-r--r--pimd/pimd.c2
-rw-r--r--pimd/subdir.am1
-rw-r--r--zebra/zebra_mlag.h1
-rw-r--r--zebra/zebra_mlag_private.c2
12 files changed, 396 insertions, 146 deletions
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index a3e5151a78..2de5a7923b 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -909,7 +909,7 @@ static void igmp_show_interface_join(struct pim_instance *pim, struct vty *vty)
static void pim_show_interfaces_single(struct pim_instance *pim,
struct vty *vty, const char *ifname,
- bool uj)
+ bool mlag, bool uj)
{
struct in_addr ifaddr;
struct interface *ifp;
@@ -952,6 +952,9 @@ static void pim_show_interfaces_single(struct pim_instance *pim,
if (!pim_ifp)
continue;
+ if (mlag == true && pim_ifp->activeactive == false)
+ continue;
+
if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
continue;
@@ -1380,7 +1383,7 @@ static void igmp_show_statistics(struct pim_instance *pim, struct vty *vty,
}
static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
- bool uj)
+ bool mlag, bool uj)
{
struct interface *ifp;
struct pim_interface *pim_ifp;
@@ -1400,6 +1403,9 @@ static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
if (!pim_ifp)
continue;
+ if (mlag == true && pim_ifp->activeactive == false)
+ continue;
+
pim_nbrs = pim_ifp->pim_neighbor_list->count;
pim_ifchannels = pim_if_ifchannel_count(pim_ifp);
fhr = 0;
@@ -4295,6 +4301,113 @@ DEFUN (show_ip_igmp_statistics,
return CMD_SUCCESS;
}
+DEFUN (show_ip_pim_mlag_summary,
+ show_ip_pim_mlag_summary_cmd,
+ "show ip pim mlag summary [json]",
+ SHOW_STR
+ IP_STR
+ PIM_STR
+ "MLAG\n"
+ "status and stats\n"
+ JSON_STR)
+{
+ bool uj = use_json(argc, argv);
+ char role_buf[MLAG_ROLE_STRSIZE];
+ char addr_buf[INET_ADDRSTRLEN];
+
+ if (uj) {
+ json_object *json = NULL;
+ json_object *json_stat = NULL;
+
+ json = json_object_new_object();
+ if (router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)
+ json_object_boolean_true_add(json, "mlagConnUp");
+ if (router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)
+ json_object_boolean_true_add(json, "mlagPeerConnUp");
+ if (router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)
+ json_object_boolean_true_add(json, "mlagPeerZebraUp");
+ json_object_string_add(json, "mlagRole",
+ mlag_role2str(router->mlag_role,
+ role_buf, sizeof(role_buf)));
+ inet_ntop(AF_INET, &router->local_vtep_ip,
+ addr_buf, INET_ADDRSTRLEN);
+ json_object_string_add(json, "localVtepIp", addr_buf);
+ inet_ntop(AF_INET, &router->anycast_vtep_ip,
+ addr_buf, INET_ADDRSTRLEN);
+ json_object_string_add(json, "anycastVtepIp", addr_buf);
+ json_object_string_add(json, "peerlinkRif",
+ router->peerlink_rif);
+
+ json_stat = json_object_new_object();
+ json_object_int_add(json_stat, "mlagConnFlaps",
+ router->mlag_stats.mlagd_session_downs);
+ json_object_int_add(json_stat, "mlagPeerConnFlaps",
+ router->mlag_stats.peer_session_downs);
+ json_object_int_add(json_stat, "mlagPeerZebraFlaps",
+ router->mlag_stats.peer_zebra_downs);
+ json_object_int_add(json_stat, "mrouteAddRx",
+ router->mlag_stats.msg.mroute_add_rx);
+ json_object_int_add(json_stat, "mrouteAddTx",
+ router->mlag_stats.msg.mroute_add_tx);
+ json_object_int_add(json_stat, "mrouteDelRx",
+ router->mlag_stats.msg.mroute_del_rx);
+ json_object_int_add(json_stat, "mrouteDelTx",
+ router->mlag_stats.msg.mroute_del_tx);
+ json_object_int_add(json_stat, "mlagStatusUpdates",
+ router->mlag_stats.msg.mlag_status_updates);
+ json_object_int_add(json_stat, "peerZebraStatusUpdates",
+ router->mlag_stats.msg.peer_zebra_status_updates);
+ json_object_int_add(json_stat, "pimStatusUpdates",
+ router->mlag_stats.msg.pim_status_updates);
+ json_object_int_add(json_stat, "vxlanUpdates",
+ router->mlag_stats.msg.vxlan_updates);
+ json_object_object_add(json, "connStats", json_stat);
+
+ vty_out(vty, "%s\n", json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ return CMD_SUCCESS;
+ }
+
+ vty_out(vty, "MLAG daemon connection: %s\n",
+ (router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)
+ ? "up" : "down");
+ vty_out(vty, "MLAG peer state: %s\n",
+ (router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)
+ ? "up" : "down");
+ vty_out(vty, "Zebra peer state: %s\n",
+ (router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)
+ ? "up" : "down");
+ vty_out(vty, "MLAG role: %s\n",
+ mlag_role2str(router->mlag_role, role_buf, sizeof(role_buf)));
+ inet_ntop(AF_INET, &router->local_vtep_ip,
+ addr_buf, INET_ADDRSTRLEN);
+ vty_out(vty, "Local VTEP IP: %s\n", addr_buf);
+ inet_ntop(AF_INET, &router->anycast_vtep_ip,
+ addr_buf, INET_ADDRSTRLEN);
+ vty_out(vty, "Anycast VTEP IP: %s\n", addr_buf);
+ vty_out(vty, "Peerlink: %s\n", router->peerlink_rif);
+ vty_out(vty, "Session flaps: mlagd: %d mlag-peer: %d zebra-peer: %d\n",
+ router->mlag_stats.mlagd_session_downs,
+ router->mlag_stats.peer_session_downs,
+ router->mlag_stats.peer_zebra_downs);
+ vty_out(vty, "Message Statistics:\n");
+ vty_out(vty, " mroute adds: rx: %d, tx: %d\n",
+ router->mlag_stats.msg.mroute_add_rx,
+ router->mlag_stats.msg.mroute_add_tx);
+ vty_out(vty, " mroute dels: rx: %d, tx: %d\n",
+ router->mlag_stats.msg.mroute_del_rx,
+ router->mlag_stats.msg.mroute_del_tx);
+ vty_out(vty, " peer zebra status updates: %d\n",
+ router->mlag_stats.msg.peer_zebra_status_updates);
+ vty_out(vty, " PIM status updates: %d\n",
+ router->mlag_stats.msg.pim_status_updates);
+ vty_out(vty, " VxLAN updates: %d\n",
+ router->mlag_stats.msg.vxlan_updates);
+
+ return CMD_SUCCESS;
+}
+
DEFUN (show_ip_pim_assert,
show_ip_pim_assert_cmd,
"show ip pim [vrf NAME] assert",
@@ -4377,10 +4490,11 @@ DEFUN (show_ip_pim_assert_winner_metric,
DEFUN (show_ip_pim_interface,
show_ip_pim_interface_cmd,
- "show ip pim [vrf NAME] interface [detail|WORD] [json]",
+ "show ip pim [mlag] [vrf NAME] interface [detail|WORD] [json]",
SHOW_STR
IP_STR
PIM_STR
+ "MLAG\n"
VRF_CMD_HELP_STR
"PIM interface information\n"
"Detailed output\n"
@@ -4390,36 +4504,47 @@ DEFUN (show_ip_pim_interface,
int idx = 2;
struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
bool uj = use_json(argc, argv);
+ bool mlag = false;
if (!vrf)
return CMD_WARNING;
+ if (argv_find(argv, argc, "mlag", &idx))
+ mlag = true;
+
if (argv_find(argv, argc, "WORD", &idx)
|| argv_find(argv, argc, "detail", &idx))
- pim_show_interfaces_single(vrf->info, vty, argv[idx]->arg, uj);
+ pim_show_interfaces_single(vrf->info, vty, argv[idx]->arg, mlag,
+ uj);
else
- pim_show_interfaces(vrf->info, vty, uj);
+ pim_show_interfaces(vrf->info, vty, mlag, uj);
return CMD_SUCCESS;
}
DEFUN (show_ip_pim_interface_vrf_all,
show_ip_pim_interface_vrf_all_cmd,
- "show ip pim vrf all interface [detail|WORD] [json]",
+ "show ip pim [mlag] vrf all interface [detail|WORD] [json]",
SHOW_STR
IP_STR
PIM_STR
+ "MLAG\n"
VRF_CMD_HELP_STR
"PIM interface information\n"
"Detailed output\n"
"interface name\n"
JSON_STR)
{
- int idx = 6;
+ int idx = 2;
bool uj = use_json(argc, argv);
struct vrf *vrf;
bool first = true;
+ bool mlag = false;
+ if (argv_find(argv, argc, "mlag", &idx))
+ mlag = true;
+
+ idx = 6;
if (uj)
vty_out(vty, "{ ");
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
@@ -4433,9 +4558,9 @@ DEFUN (show_ip_pim_interface_vrf_all,
if (argv_find(argv, argc, "WORD", &idx)
|| argv_find(argv, argc, "detail", &idx))
pim_show_interfaces_single(vrf->info, vty,
- argv[idx]->arg, uj);
+ argv[idx]->arg, mlag, uj);
else
- pim_show_interfaces(vrf->info, vty, uj);
+ pim_show_interfaces(vrf->info, vty, mlag, uj);
}
if (uj)
vty_out(vty, "}\n");
@@ -4625,113 +4750,6 @@ DEFUN (show_ip_pim_local_membership,
return CMD_SUCCESS;
}
-DEFUN (show_ip_pim_mlag_summary,
- show_ip_pim_mlag_summary_cmd,
- "show ip pim mlag summary [json]",
- SHOW_STR
- IP_STR
- PIM_STR
- "MLAG\n"
- "status and stats\n"
- JSON_STR)
-{
- bool uj = use_json(argc, argv);
- char role_buf[MLAG_ROLE_STRSIZE];
- char addr_buf[INET_ADDRSTRLEN];
-
- if (uj) {
- json_object *json = NULL;
- json_object *json_stat = NULL;
-
- json = json_object_new_object();
- if (router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)
- json_object_boolean_true_add(json, "mlagConnUp");
- if (router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)
- json_object_boolean_true_add(json, "mlagPeerConnUp");
- if (router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)
- json_object_boolean_true_add(json, "mlagPeerZebraUp");
- json_object_string_add(json, "mlagRole",
- mlag_role2str(router->mlag_role,
- role_buf, sizeof(role_buf)));
- inet_ntop(AF_INET, &router->local_vtep_ip,
- addr_buf, INET_ADDRSTRLEN);
- json_object_string_add(json, "localVtepIp", addr_buf);
- inet_ntop(AF_INET, &router->anycast_vtep_ip,
- addr_buf, INET_ADDRSTRLEN);
- json_object_string_add(json, "anycastVtepIp", addr_buf);
- json_object_string_add(json, "peerlinkRif",
- router->peerlink_rif);
-
- json_stat = json_object_new_object();
- json_object_int_add(json_stat, "mlagConnFlaps",
- router->mlag_stats.mlagd_session_downs);
- json_object_int_add(json_stat, "mlagPeerConnFlaps",
- router->mlag_stats.peer_session_downs);
- json_object_int_add(json_stat, "mlagPeerZebraFlaps",
- router->mlag_stats.peer_zebra_downs);
- json_object_int_add(json_stat, "mrouteAddRx",
- router->mlag_stats.msg.mroute_add_rx);
- json_object_int_add(json_stat, "mrouteAddTx",
- router->mlag_stats.msg.mroute_add_tx);
- json_object_int_add(json_stat, "mrouteDelRx",
- router->mlag_stats.msg.mroute_del_rx);
- json_object_int_add(json_stat, "mrouteDelTx",
- router->mlag_stats.msg.mroute_del_tx);
- json_object_int_add(json_stat, "mlagStatusUpdates",
- router->mlag_stats.msg.mlag_status_updates);
- json_object_int_add(json_stat, "peerZebraStatusUpdates",
- router->mlag_stats.msg.peer_zebra_status_updates);
- json_object_int_add(json_stat, "pimStatusUpdates",
- router->mlag_stats.msg.pim_status_updates);
- json_object_int_add(json_stat, "vxlanUpdates",
- router->mlag_stats.msg.vxlan_updates);
- json_object_object_add(json, "connStats", json_stat);
-
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
- return CMD_SUCCESS;
- }
-
- vty_out(vty, "MLAG daemon connection: %s\n",
- (router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)
- ? "up" : "down");
- vty_out(vty, "MLAG peer state: %s\n",
- (router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)
- ? "up" : "down");
- vty_out(vty, "Zebra peer state: %s\n",
- (router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)
- ? "up" : "down");
- vty_out(vty, "MLAG role: %s\n",
- mlag_role2str(router->mlag_role, role_buf, sizeof(role_buf)));
- inet_ntop(AF_INET, &router->local_vtep_ip,
- addr_buf, INET_ADDRSTRLEN);
- vty_out(vty, "Local VTEP IP: %s\n", addr_buf);
- inet_ntop(AF_INET, &router->anycast_vtep_ip,
- addr_buf, INET_ADDRSTRLEN);
- vty_out(vty, "Anycast VTEP IP: %s\n", addr_buf);
- vty_out(vty, "Peerlink: %s\n", router->peerlink_rif);
- vty_out(vty, "Session flaps: mlagd: %d mlag-peer: %d zebra-peer: %d\n",
- router->mlag_stats.mlagd_session_downs,
- router->mlag_stats.peer_session_downs,
- router->mlag_stats.peer_zebra_downs);
- vty_out(vty, "Message Statistics:\n");
- vty_out(vty, " mroute adds: rx: %d, tx: %d\n",
- router->mlag_stats.msg.mroute_add_rx,
- router->mlag_stats.msg.mroute_add_tx);
- vty_out(vty, " mroute dels: rx: %d, tx: %d\n",
- router->mlag_stats.msg.mroute_del_rx,
- router->mlag_stats.msg.mroute_del_tx);
- vty_out(vty, " peer zebra status updates: %d\n",
- router->mlag_stats.msg.peer_zebra_status_updates);
- vty_out(vty, " PIM status updates: %d\n",
- router->mlag_stats.msg.pim_status_updates);
- vty_out(vty, " VxLAN updates: %d\n",
- router->mlag_stats.msg.vxlan_updates);
-
- return CMD_SUCCESS;
-}
-
static void pim_show_mlag_up_entry_detail(struct vrf *vrf,
struct vty *vty, struct pim_upstream *up,
char *src_str, char *grp_str, json_object *json)
@@ -8035,13 +8053,13 @@ DEFPY_HIDDEN (pim_test_sg_keepalive,
return CMD_SUCCESS;
}
-DEFPY_HIDDEN (interface_ip_pim_activeactive,
- interface_ip_pim_activeactive_cmd,
- "[no$no] ip pim active-active",
- NO_STR
- IP_STR
- PIM_STR
- "Mark interface as Active-Active for MLAG operations, Hidden because not finished yet\n")
+DEFPY (interface_ip_pim_activeactive,
+ interface_ip_pim_activeactive_cmd,
+ "[no$no] ip pim active-active",
+ NO_STR
+ IP_STR
+ PIM_STR
+ "Mark interface as Active-Active for MLAG operations, Hidden because not finished yet\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct pim_interface *pim_ifp;
@@ -8051,6 +8069,11 @@ DEFPY_HIDDEN (interface_ip_pim_activeactive,
return CMD_WARNING_CONFIG_FAILED;
}
+
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("%sConfiguring PIM active-active on Interface: %s",
+ no ? "Un-":" ", ifp->name);
+
pim_ifp = ifp->info;
if (no)
pim_if_unconfigure_mlag_dualactive(pim_ifp);
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index ead9d6dbcc..528c93ce16 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -1073,6 +1073,9 @@ int pim_ifchannel_local_membership_add(struct interface *ifp,
}
}
+ /* vxlan term mroutes use ipmr-lo as local member to
+ * pull down multicast vxlan tunnel traffic
+ */
up_flags = is_vxlan ? PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM :
PIM_UPSTREAM_FLAG_MASK_SRC_IGMP;
ch = pim_ifchannel_add(ifp, sg, 0, up_flags);
diff --git a/pimd/pim_mlag.c b/pimd/pim_mlag.c
index cbde45abb8..defe41674c 100644
--- a/pimd/pim_mlag.c
+++ b/pimd/pim_mlag.c
@@ -312,14 +312,6 @@ static void pim_mlag_up_peer_del_all(void)
list_delete(&temp);
}
-static int pim_mlag_signal_zpthread(void)
-{
- /* XXX - This is a temporary stub; the MLAG thread code is planned for
- * a separate commit
- */
- return (0);
-}
-
/* Send upstream entry to the local MLAG daemon (which will subsequently
* send it to the peer MLAG switch).
*/
@@ -872,7 +864,7 @@ static int pim_mlag_deregister_handler(struct thread *thread)
void pim_mlag_deregister(void)
{
/* if somebody still interested in the MLAG channel skip de-reg */
- if (router->pim_mlag_intf_cnt)
+ if (router->pim_mlag_intf_cnt || pim_vxlan_do_mlag_reg())
return;
/* not registered; nothing do */
@@ -890,10 +882,6 @@ 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++;
@@ -919,10 +907,6 @@ 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;
pim_ifp->pim->inst_mlag_intf_cnt--;
@@ -939,6 +923,7 @@ void pim_if_unconfigure_mlag_dualactive(struct pim_interface *pim_ifp)
* De-register to Zebra
*/
pim_mlag_deregister();
+ pim_mlag_param_reset();
}
}
diff --git a/pimd/pim_mlag.h b/pimd/pim_mlag.h
index dab29cc9a2..4639f56826 100644
--- a/pimd/pim_mlag.h
+++ b/pimd/pim_mlag.h
@@ -37,6 +37,12 @@ extern void pim_mlag_deregister(void);
extern int pim_zebra_mlag_process_up(void);
extern int pim_zebra_mlag_process_down(void);
extern int pim_zebra_mlag_handle_msg(struct stream *msg, int len);
+
+/* pm_zpthread.c */
+extern int pim_mlag_signal_zpthread(void);
+extern void pim_zpthread_init(void);
+extern void pim_zpthread_terminate(void);
+
extern void pim_mlag_up_local_add(struct pim_instance *pim,
struct pim_upstream *upstream);
extern void pim_mlag_up_local_del(struct pim_instance *pim,
diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c
index 0618308ba8..b165bcbee7 100644
--- a/pimd/pim_oil.c
+++ b/pimd/pim_oil.c
@@ -33,9 +33,6 @@
#include "pim_time.h"
#include "pim_vxlan.h"
-// struct list *pim_channel_oil_list = NULL;
-// struct hash *pim_channel_oil_hash = NULL;
-
static void pim_channel_update_mute(struct channel_oil *c_oil);
char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size)
@@ -174,7 +171,7 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
}
struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil,
- const char *name)
+ const char *name)
{
if (PIM_DEBUG_MROUTE) {
struct prefix_sg sg = {.src = c_oil->oil.mfcc_mcastgrp,
diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h
index 788ddaa16c..8a808afa73 100644
--- a/pimd/pim_oil.h
+++ b/pimd/pim_oil.h
@@ -130,7 +130,7 @@ void pim_channel_oil_change_iif(struct pim_instance *pim,
struct channel_oil *c_oil, int input_vif_index,
const char *name);
struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil,
- const char *name);
+ const char *name);
int pim_channel_add_oif(struct channel_oil *c_oil, struct interface *oif,
uint32_t proto_mask, const char *caller);
@@ -146,6 +146,6 @@ void pim_channel_update_oif_mute(struct channel_oil *c_oil,
void pim_channel_oil_upstream_deref(struct channel_oil *c_oil);
void pim_channel_del_inherited_oif(struct channel_oil *c_oil,
- struct interface *oif, const char *caller);
+ struct interface *oif, const char *caller);
#endif /* PIM_OIL_H */
diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c
index b5a5089ae7..8a87dfbb55 100644
--- a/pimd/pim_vty.c
+++ b/pimd/pim_vty.c
@@ -117,6 +117,11 @@ int pim_debug_config_write(struct vty *vty)
++writes;
}
+ if (PIM_DEBUG_MLAG) {
+ vty_out(vty, "debug pim mlag\n");
+ ++writes;
+ }
+
if (PIM_DEBUG_BSM) {
vty_out(vty, "debug pim bsm\n");
++writes;
diff --git a/pimd/pim_zpthread.c b/pimd/pim_zpthread.c
new file mode 100644
index 0000000000..518b024749
--- /dev/null
+++ b/pimd/pim_zpthread.c
@@ -0,0 +1,225 @@
+/*
+ * PIM for Quagga
+ * Copyright (C) 2008 Everton da Silva Marques
+ *
+ * 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 <lib/log.h>
+#include <lib/lib_errors.h>
+
+#include "pimd.h"
+#include "pim_mlag.h"
+#include "pim_zebra.h"
+
+extern struct zclient *zclient;
+
+#define PIM_MLAG_POST_LIMIT 100
+
+int32_t mlag_bulk_cnt;
+
+static void pim_mlag_zebra_fill_header(enum mlag_msg_type msg_type)
+{
+ uint32_t fill_msg_type = msg_type;
+ uint16_t data_len;
+ uint16_t msg_cnt = 1;
+
+ if (msg_type == MLAG_MSG_NONE)
+ return;
+
+ switch (msg_type) {
+ case MLAG_REGISTER:
+ case MLAG_DEREGISTER:
+ data_len = sizeof(struct mlag_msg);
+ break;
+ case MLAG_MROUTE_ADD:
+ data_len = sizeof(struct mlag_mroute_add);
+ fill_msg_type = MLAG_MROUTE_ADD_BULK;
+ break;
+ case MLAG_MROUTE_DEL:
+ data_len = sizeof(struct mlag_mroute_del);
+ fill_msg_type = MLAG_MROUTE_DEL_BULK;
+ break;
+ default:
+ data_len = 0;
+ break;
+ }
+
+ stream_reset(router->mlag_stream);
+ /* ADD Hedaer */
+ stream_putl(router->mlag_stream, fill_msg_type);
+ /*
+ * In case of Bulk actual size & msg_cnt will be updated
+ * just before writing onto zebra
+ */
+ stream_putw(router->mlag_stream, data_len);
+ stream_putw(router->mlag_stream, msg_cnt);
+
+ if (PIM_DEBUG_MLAG)
+ zlog_debug(":%s: msg_type: %d/%d len %d",
+ __func__, msg_type, fill_msg_type, data_len);
+}
+
+static void pim_mlag_zebra_flush_buffer(void)
+{
+ uint32_t msg_type;
+
+ /* Stream had bulk messages update the Hedaer */
+ if (mlag_bulk_cnt > 1) {
+ /*
+ * No need to reset the pointer, below api reads from data[0]
+ */
+ STREAM_GETL(router->mlag_stream, msg_type);
+ if (msg_type == MLAG_MROUTE_ADD_BULK) {
+ stream_putw_at(
+ router->mlag_stream, 4,
+ (mlag_bulk_cnt * sizeof(struct mlag_mroute_add)));
+ stream_putw_at(router->mlag_stream, 6, mlag_bulk_cnt);
+ } else if (msg_type == MLAG_MROUTE_DEL_BULK) {
+ stream_putw_at(
+ router->mlag_stream, 4,
+ (mlag_bulk_cnt * sizeof(struct mlag_mroute_del)));
+ stream_putw_at(router->mlag_stream, 6, mlag_bulk_cnt);
+ } else {
+ flog_err(EC_LIB_ZAPI_ENCODE,
+ "unknown bulk message type %d bulk_count %d",
+ msg_type, mlag_bulk_cnt);
+ stream_reset(router->mlag_stream);
+ mlag_bulk_cnt = 0;
+ return;
+ }
+ }
+
+ zclient_send_mlag_data(zclient, router->mlag_stream);
+stream_failure:
+ stream_reset(router->mlag_stream);
+ mlag_bulk_cnt = 0;
+}
+
+/*
+ * Only ROUTE add & Delete will be bulked.
+ * Buffer will be flushed, when
+ * 1) there were no messages in the queue
+ * 2) Curr_msg_type != prev_msg_type
+ */
+
+static void pim_mlag_zebra_check_for_buffer_flush(uint32_t curr_msg_type,
+ uint32_t prev_msg_type)
+{
+ /* First Message, keep bulking */
+ if (prev_msg_type == MLAG_MSG_NONE) {
+ mlag_bulk_cnt = 1;
+ return;
+ }
+
+ /*msg type is route add & delete, keep bulking */
+ if (curr_msg_type == prev_msg_type
+ && (curr_msg_type == MLAG_MROUTE_ADD
+ || curr_msg_type == MLAG_MROUTE_DEL)) {
+ mlag_bulk_cnt++;
+ return;
+ }
+
+ pim_mlag_zebra_flush_buffer();
+}
+
+/*
+ * Thsi thread reads the clients data from the Gloabl queue and encodes with
+ * protobuf and pass on to the MLAG socket.
+ */
+static int pim_mlag_zthread_handler(struct thread *event)
+{
+ struct stream *read_s;
+ uint32_t wr_count = 0;
+ uint32_t prev_msg_type = MLAG_MSG_NONE;
+ uint32_t curr_msg_type = MLAG_MSG_NONE;
+
+ router->zpthread_mlag_write = NULL;
+ wr_count = stream_fifo_count_safe(router->mlag_fifo);
+
+ if (PIM_DEBUG_MLAG)
+ zlog_debug(":%s: Processing MLAG write, %d messages in queue",
+ __func__, wr_count);
+
+ if (wr_count == 0)
+ return 0;
+
+ for (wr_count = 0; wr_count < PIM_MLAG_POST_LIMIT; wr_count++) {
+ /* FIFO is empty,wait for teh message to be add */
+ if (stream_fifo_count_safe(router->mlag_fifo) == 0)
+ break;
+
+ read_s = stream_fifo_pop_safe(router->mlag_fifo);
+ if (!read_s) {
+ zlog_debug(":%s: Got a NULL Messages, some thing wrong",
+ __func__);
+ break;
+ }
+ STREAM_GETL(read_s, curr_msg_type);
+ /*
+ * Check for Buffer Overflow,
+ * MLAG Can't process more than 'PIM_MLAG_BUF_LIMIT' bytes
+ */
+ if (router->mlag_stream->endp + read_s->endp + ZEBRA_HEADER_SIZE
+ > MLAG_BUF_LIMIT)
+ pim_mlag_zebra_flush_buffer();
+
+ pim_mlag_zebra_check_for_buffer_flush(curr_msg_type,
+ prev_msg_type);
+
+ /*
+ * First message to Buffer, fill the Header
+ */
+ if (router->mlag_stream->endp == 0)
+ pim_mlag_zebra_fill_header(curr_msg_type);
+
+ /*
+ * add the data now
+ */
+ stream_put(router->mlag_stream, read_s->data + read_s->getp,
+ read_s->endp - read_s->getp);
+
+ stream_free(read_s);
+ prev_msg_type = curr_msg_type;
+ }
+
+stream_failure:
+ /*
+ * we are here , because
+ * 1. Queue might be empty
+ * 2. we crossed the max Q Read limit
+ * In any acse flush the buffer towards zebra
+ */
+ pim_mlag_zebra_flush_buffer();
+
+ if (wr_count >= PIM_MLAG_POST_LIMIT)
+ pim_mlag_signal_zpthread();
+
+ return 0;
+}
+
+
+int pim_mlag_signal_zpthread(void)
+{
+ if (router->master) {
+ if (PIM_DEBUG_MLAG)
+ zlog_debug(":%s: Scheduling PIM MLAG write Thread",
+ __func__);
+ thread_add_event(router->master, pim_mlag_zthread_handler, NULL,
+ 0, &router->zpthread_mlag_write);
+ }
+ return (0);
+}
diff --git a/pimd/pimd.c b/pimd/pimd.c
index a2af66fdc7..889d63c518 100644
--- a/pimd/pimd.c
+++ b/pimd/pimd.c
@@ -102,6 +102,8 @@ void pim_router_init(void)
router->packet_process = PIM_DEFAULT_PACKET_PROCESS;
router->register_probe_time = PIM_REGISTER_PROBE_TIME_DEFAULT;
router->vrf_id = VRF_DEFAULT;
+ router->pim_mlag_intf_cnt = 0;
+ router->connected_to_mlag = false;
}
void pim_router_terminate(void)
diff --git a/pimd/subdir.am b/pimd/subdir.am
index db43f0a7c6..0e30590079 100644
--- a/pimd/subdir.am
+++ b/pimd/subdir.am
@@ -63,6 +63,7 @@ pimd_libpim_a_SOURCES = \
pimd/pim_zebra.c \
pimd/pim_zlookup.c \
pimd/pim_vxlan.c \
+ pimd/pim_zpthread.c \
pimd/pimd.c \
# end
diff --git a/zebra/zebra_mlag.h b/zebra/zebra_mlag.h
index c35fa15561..d44a400666 100644
--- a/zebra/zebra_mlag.h
+++ b/zebra/zebra_mlag.h
@@ -46,6 +46,7 @@ extern uint32_t mlag_rd_buf_offset;
static inline void zebra_mlag_reset_read_buffer(void)
{
+ memset(mlag_wr_buffer, 0, ZEBRA_MLAG_BUF_LIMIT);
mlag_rd_buf_offset = 0;
}
diff --git a/zebra/zebra_mlag_private.c b/zebra/zebra_mlag_private.c
index 3024407ada..83d0d44097 100644
--- a/zebra/zebra_mlag_private.c
+++ b/zebra/zebra_mlag_private.c
@@ -78,6 +78,8 @@ static int zebra_mlag_read(struct thread *thread)
uint32_t h_msglen;
uint32_t tot_len, curr_len = mlag_rd_buf_offset;
+ zrouter.mlag_info.t_read = NULL;
+
/*
* Received message in sock_stream looks like below
* | len-1 (4 Bytes) | payload-1 (len-1) |